| 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 |