OLD | NEW |
1 // Copyright 2009 the V8 project authors. All rights reserved. | 1 // Copyright 2009 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 25 matching lines...) Expand all Loading... |
36 #include "full-codegen.h" | 36 #include "full-codegen.h" |
37 #include "oprofile-agent.h" | 37 #include "oprofile-agent.h" |
38 #include "rewriter.h" | 38 #include "rewriter.h" |
39 #include "scopes.h" | 39 #include "scopes.h" |
40 #include "usage-analyzer.h" | 40 #include "usage-analyzer.h" |
41 | 41 |
42 namespace v8 { | 42 namespace v8 { |
43 namespace internal { | 43 namespace internal { |
44 | 44 |
45 | 45 |
46 static Handle<Code> MakeCode(FunctionLiteral* literal, | 46 static Handle<Code> MakeCode(Handle<Context> context, CompilationInfo* info) { |
47 Handle<Script> script, | 47 FunctionLiteral* function = info->function(); |
48 Handle<Context> context, | 48 ASSERT(function != NULL); |
49 bool is_eval, | |
50 CompilationInfo* info) { | |
51 ASSERT(literal != NULL); | |
52 | |
53 // Rewrite the AST by introducing .result assignments where needed. | 49 // Rewrite the AST by introducing .result assignments where needed. |
54 if (!Rewriter::Process(literal) || !AnalyzeVariableUsage(literal)) { | 50 if (!Rewriter::Process(function) || !AnalyzeVariableUsage(function)) { |
55 // Signal a stack overflow by returning a null handle. The stack | 51 // Signal a stack overflow by returning a null handle. The stack |
56 // overflow exception will be thrown by the caller. | 52 // overflow exception will be thrown by the caller. |
57 return Handle<Code>::null(); | 53 return Handle<Code>::null(); |
58 } | 54 } |
59 | 55 |
60 { | 56 { |
61 // Compute top scope and allocate variables. For lazy compilation | 57 // Compute top scope and allocate variables. For lazy compilation |
62 // the top scope only contains the single lazily compiled function, | 58 // the top scope only contains the single lazily compiled function, |
63 // so this doesn't re-allocate variables repeatedly. | 59 // so this doesn't re-allocate variables repeatedly. |
64 HistogramTimerScope timer(&Counters::variable_allocation); | 60 HistogramTimerScope timer(&Counters::variable_allocation); |
65 Scope* top = literal->scope(); | 61 Scope* top = info->scope(); |
66 while (top->outer_scope() != NULL) top = top->outer_scope(); | 62 while (top->outer_scope() != NULL) top = top->outer_scope(); |
67 top->AllocateVariables(context); | 63 top->AllocateVariables(context); |
68 } | 64 } |
69 | 65 |
70 #ifdef DEBUG | 66 #ifdef DEBUG |
71 if (Bootstrapper::IsActive() ? | 67 if (Bootstrapper::IsActive() ? |
72 FLAG_print_builtin_scopes : | 68 FLAG_print_builtin_scopes : |
73 FLAG_print_scopes) { | 69 FLAG_print_scopes) { |
74 literal->scope()->Print(); | 70 info->scope()->Print(); |
75 } | 71 } |
76 #endif | 72 #endif |
77 | 73 |
78 // Optimize the AST. | 74 // Optimize the AST. |
79 if (!Rewriter::Optimize(literal)) { | 75 if (!Rewriter::Optimize(function)) { |
80 // Signal a stack overflow by returning a null handle. The stack | 76 // Signal a stack overflow by returning a null handle. The stack |
81 // overflow exception will be thrown by the caller. | 77 // overflow exception will be thrown by the caller. |
82 return Handle<Code>::null(); | 78 return Handle<Code>::null(); |
83 } | 79 } |
84 | 80 |
85 // Generate code and return it. Code generator selection is governed by | 81 // Generate code and return it. Code generator selection is governed by |
86 // which backends are enabled and whether the function is considered | 82 // which backends are enabled and whether the function is considered |
87 // run-once code or not: | 83 // run-once code or not: |
88 // | 84 // |
89 // --full-compiler enables the dedicated backend for code we expect to be | 85 // --full-compiler enables the dedicated backend for code we expect to be |
90 // run once | 86 // run once |
91 // --fast-compiler enables a speculative optimizing backend (for | 87 // --fast-compiler enables a speculative optimizing backend (for |
92 // non-run-once code) | 88 // non-run-once code) |
93 // | 89 // |
94 // The normal choice of backend can be overridden with the flags | 90 // The normal choice of backend can be overridden with the flags |
95 // --always-full-compiler and --always-fast-compiler, which are mutually | 91 // --always-full-compiler and --always-fast-compiler, which are mutually |
96 // incompatible. | 92 // incompatible. |
97 CHECK(!FLAG_always_full_compiler || !FLAG_always_fast_compiler); | 93 CHECK(!FLAG_always_full_compiler || !FLAG_always_fast_compiler); |
98 | 94 |
99 Handle<SharedFunctionInfo> shared = info->shared_info(); | 95 Handle<SharedFunctionInfo> shared = info->shared_info(); |
100 bool is_run_once = (shared.is_null()) | 96 bool is_run_once = (shared.is_null()) |
101 ? literal->scope()->is_global_scope() | 97 ? info->scope()->is_global_scope() |
102 : (shared->is_toplevel() || shared->try_full_codegen()); | 98 : (shared->is_toplevel() || shared->try_full_codegen()); |
103 | 99 |
104 if (FLAG_always_full_compiler || (FLAG_full_compiler && is_run_once)) { | 100 if (FLAG_always_full_compiler || (FLAG_full_compiler && is_run_once)) { |
105 FullCodeGenSyntaxChecker checker; | 101 FullCodeGenSyntaxChecker checker; |
106 checker.Check(literal); | 102 checker.Check(function); |
107 if (checker.has_supported_syntax()) { | 103 if (checker.has_supported_syntax()) { |
108 return FullCodeGenerator::MakeCode(literal, script, is_eval); | 104 return FullCodeGenerator::MakeCode(info); |
109 } | 105 } |
110 } else if (FLAG_always_fast_compiler || | 106 } else if (FLAG_always_fast_compiler || |
111 (FLAG_fast_compiler && !is_run_once)) { | 107 (FLAG_fast_compiler && !is_run_once)) { |
112 FastCodeGenSyntaxChecker checker; | 108 FastCodeGenSyntaxChecker checker; |
113 checker.Check(literal, info); | 109 checker.Check(info); |
114 if (checker.has_supported_syntax()) { | 110 if (checker.has_supported_syntax()) { |
115 return FastCodeGenerator::MakeCode(literal, script, is_eval, info); | 111 return FastCodeGenerator::MakeCode(info); |
116 } | 112 } |
117 } | 113 } |
118 | 114 |
119 return CodeGenerator::MakeCode(literal, script, is_eval, info); | 115 return CodeGenerator::MakeCode(info); |
120 } | 116 } |
121 | 117 |
122 | 118 |
123 static Handle<JSFunction> MakeFunction(bool is_global, | 119 static Handle<JSFunction> MakeFunction(bool is_global, |
124 bool is_eval, | 120 bool is_eval, |
125 Compiler::ValidationState validate, | 121 Compiler::ValidationState validate, |
126 Handle<Script> script, | 122 Handle<Script> script, |
127 Handle<Context> context, | 123 Handle<Context> context, |
128 v8::Extension* extension, | 124 v8::Extension* extension, |
129 ScriptDataImpl* pre_data) { | 125 ScriptDataImpl* pre_data) { |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
173 | 169 |
174 // Measure how long it takes to do the compilation; only take the | 170 // Measure how long it takes to do the compilation; only take the |
175 // rest of the function into account to avoid overlap with the | 171 // rest of the function into account to avoid overlap with the |
176 // parsing statistics. | 172 // parsing statistics. |
177 HistogramTimer* rate = is_eval | 173 HistogramTimer* rate = is_eval |
178 ? &Counters::compile_eval | 174 ? &Counters::compile_eval |
179 : &Counters::compile; | 175 : &Counters::compile; |
180 HistogramTimerScope timer(rate); | 176 HistogramTimerScope timer(rate); |
181 | 177 |
182 // Compile the code. | 178 // Compile the code. |
183 CompilationInfo info(Handle<SharedFunctionInfo>::null(), | 179 CompilationInfo info(lit, script, is_eval); |
184 Handle<Object>::null(), // No receiver. | 180 Handle<Code> code = MakeCode(context, &info); |
185 0); // Not nested in a loop. | |
186 Handle<Code> code = MakeCode(lit, script, context, is_eval, &info); | |
187 | 181 |
188 // Check for stack-overflow exceptions. | 182 // Check for stack-overflow exceptions. |
189 if (code.is_null()) { | 183 if (code.is_null()) { |
190 Top::StackOverflow(); | 184 Top::StackOverflow(); |
191 return Handle<JSFunction>::null(); | 185 return Handle<JSFunction>::null(); |
192 } | 186 } |
193 | 187 |
194 #if defined ENABLE_LOGGING_AND_PROFILING || defined ENABLE_OPROFILE_AGENT | 188 #if defined ENABLE_LOGGING_AND_PROFILING || defined ENABLE_OPROFILE_AGENT |
195 // Log the code generation for the script. Check explicit whether logging is | 189 // Log the code generation for the script. Check explicit whether logging is |
196 // to avoid allocating when not required. | 190 // to avoid allocating when not required. |
(...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
348 CompilationZoneScope zone_scope(DELETE_ON_EXIT); | 342 CompilationZoneScope zone_scope(DELETE_ON_EXIT); |
349 | 343 |
350 // The VM is in the COMPILER state until exiting this function. | 344 // The VM is in the COMPILER state until exiting this function. |
351 VMState state(COMPILER); | 345 VMState state(COMPILER); |
352 | 346 |
353 PostponeInterruptsScope postpone; | 347 PostponeInterruptsScope postpone; |
354 | 348 |
355 // Compute name, source code and script data. | 349 // Compute name, source code and script data. |
356 Handle<SharedFunctionInfo> shared = info->shared_info(); | 350 Handle<SharedFunctionInfo> shared = info->shared_info(); |
357 Handle<String> name(String::cast(shared->name())); | 351 Handle<String> name(String::cast(shared->name())); |
358 Handle<Script> script(Script::cast(shared->script())); | |
359 | 352 |
360 int start_position = shared->start_position(); | 353 int start_position = shared->start_position(); |
361 int end_position = shared->end_position(); | 354 int end_position = shared->end_position(); |
362 bool is_expression = shared->is_expression(); | 355 bool is_expression = shared->is_expression(); |
363 Counters::total_compile_size.Increment(end_position - start_position); | 356 Counters::total_compile_size.Increment(end_position - start_position); |
364 | 357 |
365 // Generate the AST for the lazily compiled function. The AST may be | 358 // Generate the AST for the lazily compiled function. The AST may be |
366 // NULL in case of parser stack overflow. | 359 // NULL in case of parser stack overflow. |
367 FunctionLiteral* lit = MakeLazyAST(script, name, | 360 FunctionLiteral* lit = MakeLazyAST(info->script(), |
| 361 name, |
368 start_position, | 362 start_position, |
369 end_position, | 363 end_position, |
370 is_expression); | 364 is_expression); |
371 | 365 |
372 // Check for parse errors. | 366 // Check for parse errors. |
373 if (lit == NULL) { | 367 if (lit == NULL) { |
374 ASSERT(Top::has_pending_exception()); | 368 ASSERT(Top::has_pending_exception()); |
375 return false; | 369 return false; |
376 } | 370 } |
| 371 info->set_function(lit); |
377 | 372 |
378 // Measure how long it takes to do the lazy compilation; only take | 373 // Measure how long it takes to do the lazy compilation; only take |
379 // the rest of the function into account to avoid overlap with the | 374 // the rest of the function into account to avoid overlap with the |
380 // lazy parsing statistics. | 375 // lazy parsing statistics. |
381 HistogramTimerScope timer(&Counters::compile_lazy); | 376 HistogramTimerScope timer(&Counters::compile_lazy); |
382 | 377 |
383 // Compile the code. | 378 // Compile the code. |
384 Handle<Code> code = MakeCode(lit, | 379 Handle<Code> code = MakeCode(Handle<Context>::null(), info); |
385 script, | |
386 Handle<Context>::null(), | |
387 false, | |
388 info); | |
389 | 380 |
390 // Check for stack-overflow exception. | 381 // Check for stack-overflow exception. |
391 if (code.is_null()) { | 382 if (code.is_null()) { |
392 Top::StackOverflow(); | 383 Top::StackOverflow(); |
393 return false; | 384 return false; |
394 } | 385 } |
395 | 386 |
396 #if defined ENABLE_LOGGING_AND_PROFILING || defined ENABLE_OPROFILE_AGENT | 387 #if defined ENABLE_LOGGING_AND_PROFILING || defined ENABLE_OPROFILE_AGENT |
397 // Log the code generation. If source information is available include script | 388 // Log the code generation. If source information is available include script |
398 // name and line number. Check explicit whether logging is enabled as finding | 389 // name and line number. Check explicit whether logging is enabled as finding |
399 // the line number is not for free. | 390 // the line number is not for free. |
400 if (Logger::is_logging() || OProfileAgent::is_enabled()) { | 391 if (Logger::is_logging() || OProfileAgent::is_enabled()) { |
401 Handle<String> func_name(name->length() > 0 ? | 392 Handle<String> func_name(name->length() > 0 ? |
402 *name : shared->inferred_name()); | 393 *name : shared->inferred_name()); |
| 394 Handle<Script> script = info->script(); |
403 if (script->name()->IsString()) { | 395 if (script->name()->IsString()) { |
404 int line_num = GetScriptLineNumber(script, start_position) + 1; | 396 int line_num = GetScriptLineNumber(script, start_position) + 1; |
405 LOG(CodeCreateEvent(Logger::LAZY_COMPILE_TAG, *code, *func_name, | 397 LOG(CodeCreateEvent(Logger::LAZY_COMPILE_TAG, *code, *func_name, |
406 String::cast(script->name()), line_num)); | 398 String::cast(script->name()), line_num)); |
407 OProfileAgent::CreateNativeCodeRegion(*func_name, | 399 OProfileAgent::CreateNativeCodeRegion(*func_name, |
408 String::cast(script->name()), | 400 String::cast(script->name()), |
409 line_num, | 401 line_num, |
410 code->instruction_start(), | 402 code->instruction_start(), |
411 code->instruction_size()); | 403 code->instruction_size()); |
412 } else { | 404 } else { |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
459 } else { | 451 } else { |
460 // The bodies of function literals have not yet been visited by | 452 // The bodies of function literals have not yet been visited by |
461 // the AST optimizer/analyzer. | 453 // the AST optimizer/analyzer. |
462 if (!Rewriter::Optimize(literal)) { | 454 if (!Rewriter::Optimize(literal)) { |
463 return Handle<JSFunction>::null(); | 455 return Handle<JSFunction>::null(); |
464 } | 456 } |
465 | 457 |
466 // Generate code and return it. The way that the compilation mode | 458 // Generate code and return it. The way that the compilation mode |
467 // is controlled by the command-line flags is described in | 459 // is controlled by the command-line flags is described in |
468 // the static helper function MakeCode. | 460 // the static helper function MakeCode. |
469 CompilationInfo info(Handle<SharedFunctionInfo>::null(), | 461 CompilationInfo info(literal, script, false); |
470 Handle<Object>::null(), // No receiver. | |
471 0); // Not nested in a loop. | |
472 | 462 |
473 CHECK(!FLAG_always_full_compiler || !FLAG_always_fast_compiler); | 463 CHECK(!FLAG_always_full_compiler || !FLAG_always_fast_compiler); |
474 bool is_run_once = literal->try_full_codegen(); | 464 bool is_run_once = literal->try_full_codegen(); |
475 bool is_compiled = false; | 465 bool is_compiled = false; |
476 if (FLAG_always_full_compiler || (FLAG_full_compiler && is_run_once)) { | 466 if (FLAG_always_full_compiler || (FLAG_full_compiler && is_run_once)) { |
477 FullCodeGenSyntaxChecker checker; | 467 FullCodeGenSyntaxChecker checker; |
478 checker.Check(literal); | 468 checker.Check(literal); |
479 if (checker.has_supported_syntax()) { | 469 if (checker.has_supported_syntax()) { |
480 code = FullCodeGenerator::MakeCode(literal, | 470 code = FullCodeGenerator::MakeCode(&info); |
481 script, | |
482 false); // Not eval. | |
483 is_compiled = true; | 471 is_compiled = true; |
484 } | 472 } |
485 } else if (FLAG_always_fast_compiler || | 473 } else if (FLAG_always_fast_compiler || |
486 (FLAG_fast_compiler && !is_run_once)) { | 474 (FLAG_fast_compiler && !is_run_once)) { |
487 // Since we are not lazily compiling we do not have a receiver to | 475 // Since we are not lazily compiling we do not have a receiver to |
488 // specialize for. | 476 // specialize for. |
489 FastCodeGenSyntaxChecker checker; | 477 FastCodeGenSyntaxChecker checker; |
490 checker.Check(literal, &info); | 478 checker.Check(&info); |
491 if (checker.has_supported_syntax()) { | 479 if (checker.has_supported_syntax()) { |
492 code = FastCodeGenerator::MakeCode(literal, script, false, &info); | 480 code = FastCodeGenerator::MakeCode(&info); |
493 is_compiled = true; | 481 is_compiled = true; |
494 } | 482 } |
495 } | 483 } |
496 | 484 |
497 if (!is_compiled) { | 485 if (!is_compiled) { |
498 // We fall back to the classic V8 code generator. | 486 // We fall back to the classic V8 code generator. |
499 code = CodeGenerator::MakeCode(literal, | 487 code = CodeGenerator::MakeCode(&info); |
500 script, | |
501 false, // Not eval. | |
502 &info); | |
503 } | 488 } |
504 | 489 |
505 // Check for stack-overflow exception. | 490 // Check for stack-overflow exception. |
506 if (code.is_null()) { | 491 if (code.is_null()) { |
507 caller->SetStackOverflow(); | 492 caller->SetStackOverflow(); |
508 return Handle<JSFunction>::null(); | 493 return Handle<JSFunction>::null(); |
509 } | 494 } |
510 | 495 |
511 // Function compilation complete. | 496 // Function compilation complete. |
512 LOG(CodeCreateEvent(Logger::FUNCTION_TAG, *code, *literal->name())); | 497 LOG(CodeCreateEvent(Logger::FUNCTION_TAG, *code, *literal->name())); |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
556 fun->shared()->set_is_toplevel(is_toplevel); | 541 fun->shared()->set_is_toplevel(is_toplevel); |
557 fun->shared()->set_inferred_name(*lit->inferred_name()); | 542 fun->shared()->set_inferred_name(*lit->inferred_name()); |
558 fun->shared()->SetThisPropertyAssignmentsInfo( | 543 fun->shared()->SetThisPropertyAssignmentsInfo( |
559 lit->has_only_simple_this_property_assignments(), | 544 lit->has_only_simple_this_property_assignments(), |
560 *lit->this_property_assignments()); | 545 *lit->this_property_assignments()); |
561 fun->shared()->set_try_full_codegen(lit->try_full_codegen()); | 546 fun->shared()->set_try_full_codegen(lit->try_full_codegen()); |
562 } | 547 } |
563 | 548 |
564 | 549 |
565 } } // namespace v8::internal | 550 } } // namespace v8::internal |
OLD | NEW |