| 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 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 352 CompilationZoneScope zone_scope(DELETE_ON_EXIT); | 346 CompilationZoneScope zone_scope(DELETE_ON_EXIT); |
| 353 | 347 |
| 354 // The VM is in the COMPILER state until exiting this function. | 348 // The VM is in the COMPILER state until exiting this function. |
| 355 VMState state(COMPILER); | 349 VMState state(COMPILER); |
| 356 | 350 |
| 357 PostponeInterruptsScope postpone; | 351 PostponeInterruptsScope postpone; |
| 358 | 352 |
| 359 // Compute name, source code and script data. | 353 // Compute name, source code and script data. |
| 360 Handle<SharedFunctionInfo> shared = info->shared_info(); | 354 Handle<SharedFunctionInfo> shared = info->shared_info(); |
| 361 Handle<String> name(String::cast(shared->name())); | 355 Handle<String> name(String::cast(shared->name())); |
| 362 Handle<Script> script(Script::cast(shared->script())); | |
| 363 | 356 |
| 364 int start_position = shared->start_position(); | 357 int start_position = shared->start_position(); |
| 365 int end_position = shared->end_position(); | 358 int end_position = shared->end_position(); |
| 366 bool is_expression = shared->is_expression(); | 359 bool is_expression = shared->is_expression(); |
| 367 Counters::total_compile_size.Increment(end_position - start_position); | 360 Counters::total_compile_size.Increment(end_position - start_position); |
| 368 | 361 |
| 369 // Generate the AST for the lazily compiled function. The AST may be | 362 // Generate the AST for the lazily compiled function. The AST may be |
| 370 // NULL in case of parser stack overflow. | 363 // NULL in case of parser stack overflow. |
| 371 FunctionLiteral* lit = MakeLazyAST(script, name, | 364 FunctionLiteral* lit = MakeLazyAST(info->script(), |
| 365 name, |
| 372 start_position, | 366 start_position, |
| 373 end_position, | 367 end_position, |
| 374 is_expression); | 368 is_expression); |
| 375 | 369 |
| 376 // Check for parse errors. | 370 // Check for parse errors. |
| 377 if (lit == NULL) { | 371 if (lit == NULL) { |
| 378 ASSERT(Top::has_pending_exception()); | 372 ASSERT(Top::has_pending_exception()); |
| 379 return false; | 373 return false; |
| 380 } | 374 } |
| 375 info->set_function(lit); |
| 381 | 376 |
| 382 // Measure how long it takes to do the lazy compilation; only take | 377 // Measure how long it takes to do the lazy compilation; only take |
| 383 // the rest of the function into account to avoid overlap with the | 378 // the rest of the function into account to avoid overlap with the |
| 384 // lazy parsing statistics. | 379 // lazy parsing statistics. |
| 385 HistogramTimerScope timer(&Counters::compile_lazy); | 380 HistogramTimerScope timer(&Counters::compile_lazy); |
| 386 | 381 |
| 387 // Compile the code. | 382 // Compile the code. |
| 388 Handle<Code> code = MakeCode(lit, | 383 Handle<Code> code = MakeCode(Handle<Context>::null(), info); |
| 389 script, | |
| 390 Handle<Context>::null(), | |
| 391 false, | |
| 392 info); | |
| 393 | 384 |
| 394 // Check for stack-overflow exception. | 385 // Check for stack-overflow exception. |
| 395 if (code.is_null()) { | 386 if (code.is_null()) { |
| 396 Top::StackOverflow(); | 387 Top::StackOverflow(); |
| 397 return false; | 388 return false; |
| 398 } | 389 } |
| 399 | 390 |
| 400 #if defined ENABLE_LOGGING_AND_PROFILING || defined ENABLE_OPROFILE_AGENT | 391 #if defined ENABLE_LOGGING_AND_PROFILING || defined ENABLE_OPROFILE_AGENT |
| 401 LogCodeCreateEvent(Logger::LAZY_COMPILE_TAG, | 392 LogCodeCreateEvent(Logger::LAZY_COMPILE_TAG, |
| 402 name, | 393 name, |
| 403 Handle<String>(shared->inferred_name()), | 394 Handle<String>(shared->inferred_name()), |
| 404 start_position, | 395 start_position, |
| 405 script, | 396 info->script(), |
| 406 code); | 397 code); |
| 407 #endif | 398 #endif |
| 408 | 399 |
| 409 // Update the shared function info with the compiled code. | 400 // Update the shared function info with the compiled code. |
| 410 shared->set_code(*code); | 401 shared->set_code(*code); |
| 411 | 402 |
| 412 // Set the expected number of properties for instances. | 403 // Set the expected number of properties for instances. |
| 413 SetExpectedNofPropertiesFromEstimate(shared, lit->expected_property_count()); | 404 SetExpectedNofPropertiesFromEstimate(shared, lit->expected_property_count()); |
| 414 | 405 |
| 415 // Set the optimication hints after performing lazy compilation, as these are | 406 // Set the optimication hints after performing lazy compilation, as these are |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 447 } else { | 438 } else { |
| 448 // The bodies of function literals have not yet been visited by | 439 // The bodies of function literals have not yet been visited by |
| 449 // the AST optimizer/analyzer. | 440 // the AST optimizer/analyzer. |
| 450 if (!Rewriter::Optimize(literal)) { | 441 if (!Rewriter::Optimize(literal)) { |
| 451 return Handle<JSFunction>::null(); | 442 return Handle<JSFunction>::null(); |
| 452 } | 443 } |
| 453 | 444 |
| 454 // Generate code and return it. The way that the compilation mode | 445 // Generate code and return it. The way that the compilation mode |
| 455 // is controlled by the command-line flags is described in | 446 // is controlled by the command-line flags is described in |
| 456 // the static helper function MakeCode. | 447 // the static helper function MakeCode. |
| 457 CompilationInfo info(Handle<SharedFunctionInfo>::null(), | 448 CompilationInfo info(literal, script, false); |
| 458 Handle<Object>::null(), // No receiver. | |
| 459 0); // Not nested in a loop. | |
| 460 | 449 |
| 461 CHECK(!FLAG_always_full_compiler || !FLAG_always_fast_compiler); | 450 CHECK(!FLAG_always_full_compiler || !FLAG_always_fast_compiler); |
| 462 bool is_run_once = literal->try_full_codegen(); | 451 bool is_run_once = literal->try_full_codegen(); |
| 463 bool is_compiled = false; | 452 bool is_compiled = false; |
| 464 if (FLAG_always_full_compiler || (FLAG_full_compiler && is_run_once)) { | 453 if (FLAG_always_full_compiler || (FLAG_full_compiler && is_run_once)) { |
| 465 FullCodeGenSyntaxChecker checker; | 454 FullCodeGenSyntaxChecker checker; |
| 466 checker.Check(literal); | 455 checker.Check(literal); |
| 467 if (checker.has_supported_syntax()) { | 456 if (checker.has_supported_syntax()) { |
| 468 code = FullCodeGenerator::MakeCode(literal, | 457 code = FullCodeGenerator::MakeCode(&info); |
| 469 script, | |
| 470 false); // Not eval. | |
| 471 is_compiled = true; | 458 is_compiled = true; |
| 472 } | 459 } |
| 473 } else if (FLAG_always_fast_compiler || | 460 } else if (FLAG_always_fast_compiler || |
| 474 (FLAG_fast_compiler && !is_run_once)) { | 461 (FLAG_fast_compiler && !is_run_once)) { |
| 475 // Since we are not lazily compiling we do not have a receiver to | 462 // Since we are not lazily compiling we do not have a receiver to |
| 476 // specialize for. | 463 // specialize for. |
| 477 FastCodeGenSyntaxChecker checker; | 464 FastCodeGenSyntaxChecker checker; |
| 478 checker.Check(literal, &info); | 465 checker.Check(&info); |
| 479 if (checker.has_supported_syntax()) { | 466 if (checker.has_supported_syntax()) { |
| 480 code = FastCodeGenerator::MakeCode(literal, script, false, &info); | 467 code = FastCodeGenerator::MakeCode(&info); |
| 481 is_compiled = true; | 468 is_compiled = true; |
| 482 } | 469 } |
| 483 } | 470 } |
| 484 | 471 |
| 485 if (!is_compiled) { | 472 if (!is_compiled) { |
| 486 // We fall back to the classic V8 code generator. | 473 // We fall back to the classic V8 code generator. |
| 487 code = CodeGenerator::MakeCode(literal, | 474 code = CodeGenerator::MakeCode(&info); |
| 488 script, | |
| 489 false, // Not eval. | |
| 490 &info); | |
| 491 } | 475 } |
| 492 | 476 |
| 493 // Check for stack-overflow exception. | 477 // Check for stack-overflow exception. |
| 494 if (code.is_null()) { | 478 if (code.is_null()) { |
| 495 caller->SetStackOverflow(); | 479 caller->SetStackOverflow(); |
| 496 return Handle<JSFunction>::null(); | 480 return Handle<JSFunction>::null(); |
| 497 } | 481 } |
| 498 | 482 |
| 499 // Function compilation complete. | 483 // Function compilation complete. |
| 500 | 484 |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 577 LOG(CodeCreateEvent(tag, *code, *func_name)); | 561 LOG(CodeCreateEvent(tag, *code, *func_name)); |
| 578 OProfileAgent::CreateNativeCodeRegion(*func_name, | 562 OProfileAgent::CreateNativeCodeRegion(*func_name, |
| 579 code->instruction_start(), | 563 code->instruction_start(), |
| 580 code->instruction_size()); | 564 code->instruction_size()); |
| 581 } | 565 } |
| 582 } | 566 } |
| 583 } | 567 } |
| 584 #endif | 568 #endif |
| 585 | 569 |
| 586 } } // namespace v8::internal | 570 } } // namespace v8::internal |
| OLD | NEW |