| OLD | NEW |
| 1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 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 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 85 // compiler will be used for all code. | 85 // compiler will be used for all code. |
| 86 static bool AlwaysFullCompiler() { | 86 static bool AlwaysFullCompiler() { |
| 87 #ifdef ENABLE_DEBUGGER_SUPPORT | 87 #ifdef ENABLE_DEBUGGER_SUPPORT |
| 88 return FLAG_always_full_compiler || Debugger::IsDebuggerActive(); | 88 return FLAG_always_full_compiler || Debugger::IsDebuggerActive(); |
| 89 #else | 89 #else |
| 90 return FLAG_always_full_compiler; | 90 return FLAG_always_full_compiler; |
| 91 #endif | 91 #endif |
| 92 } | 92 } |
| 93 | 93 |
| 94 | 94 |
| 95 static Handle<Code> MakeCode(Handle<Context> context, CompilationInfo* info) { | 95 static bool MakeCode(CompilationInfo* info) { |
| 96 FunctionLiteral* function = info->function(); | 96 // Precondition: code has been parsed. Postcondition: the code field in |
| 97 ASSERT(function != NULL); | 97 // the compilation info is set if compilation succeeded. |
| 98 // Rewrite the AST by introducing .result assignments where needed. | 98 ASSERT(info->function() != NULL); |
| 99 if (!Rewriter::Process(function)) { | 99 |
| 100 // Signal a stack overflow by returning a null handle. The stack | 100 if (Rewriter::Rewrite(info) && |
| 101 // overflow exception will be thrown by the caller. | 101 Scope::Analyze(info) && |
| 102 return Handle<Code>::null(); | 102 Rewriter::Analyze(info)) { |
| 103 // Generate code and return it. Code generator selection is governed by |
| 104 // which backends are enabled and whether the function is considered |
| 105 // run-once code or not. |
| 106 // |
| 107 // --full-compiler enables the dedicated backend for code we expect to |
| 108 // be run once |
| 109 // |
| 110 // The normal choice of backend can be overridden with the flags |
| 111 // --always-full-compiler. |
| 112 Handle<SharedFunctionInfo> shared = info->shared_info(); |
| 113 bool is_run_once = (shared.is_null()) |
| 114 ? info->scope()->is_global_scope() |
| 115 : (shared->is_toplevel() || shared->try_full_codegen()); |
| 116 bool can_use_full = |
| 117 FLAG_full_compiler && !info->function()->contains_loops(); |
| 118 if (AlwaysFullCompiler() || (is_run_once && can_use_full)) { |
| 119 return FullCodeGenerator::MakeCode(info); |
| 120 } else { |
| 121 AssignedVariablesAnalyzer ava; |
| 122 return ava.Analyze(info) && CodeGenerator::MakeCode(info); |
| 123 } |
| 103 } | 124 } |
| 104 | 125 |
| 105 { | 126 return false; |
| 106 // Compute top scope and allocate variables. For lazy compilation | |
| 107 // the top scope only contains the single lazily compiled function, | |
| 108 // so this doesn't re-allocate variables repeatedly. | |
| 109 HistogramTimerScope timer(&Counters::variable_allocation); | |
| 110 Scope* top = info->scope(); | |
| 111 while (top->outer_scope() != NULL) top = top->outer_scope(); | |
| 112 top->AllocateVariables(context); | |
| 113 } | |
| 114 | |
| 115 #ifdef DEBUG | |
| 116 if (Bootstrapper::IsActive() ? | |
| 117 FLAG_print_builtin_scopes : | |
| 118 FLAG_print_scopes) { | |
| 119 info->scope()->Print(); | |
| 120 } | |
| 121 #endif | |
| 122 | |
| 123 // Optimize the AST. | |
| 124 if (!Rewriter::Optimize(function)) { | |
| 125 // Signal a stack overflow by returning a null handle. The stack | |
| 126 // overflow exception will be thrown by the caller. | |
| 127 return Handle<Code>::null(); | |
| 128 } | |
| 129 | |
| 130 // Generate code and return it. Code generator selection is governed by | |
| 131 // which backends are enabled and whether the function is considered | |
| 132 // run-once code or not: | |
| 133 // | |
| 134 // --full-compiler enables the dedicated backend for code we expect to be | |
| 135 // run once | |
| 136 // | |
| 137 // The normal choice of backend can be overridden with the flags | |
| 138 // --always-full-compiler. | |
| 139 Handle<SharedFunctionInfo> shared = info->shared_info(); | |
| 140 bool is_run_once = (shared.is_null()) | |
| 141 ? info->scope()->is_global_scope() | |
| 142 : (shared->is_toplevel() || shared->try_full_codegen()); | |
| 143 bool use_full = FLAG_full_compiler && !function->contains_loops(); | |
| 144 if (AlwaysFullCompiler() || (use_full && is_run_once)) { | |
| 145 return FullCodeGenerator::MakeCode(info); | |
| 146 } | |
| 147 | |
| 148 AssignedVariablesAnalyzer ava(function); | |
| 149 if (!ava.Analyze()) return Handle<Code>::null(); | |
| 150 return CodeGenerator::MakeCode(info); | |
| 151 } | 127 } |
| 152 | 128 |
| 153 | 129 |
| 154 #ifdef ENABLE_DEBUGGER_SUPPORT | 130 #ifdef ENABLE_DEBUGGER_SUPPORT |
| 155 Handle<Code> MakeCodeForLiveEdit(CompilationInfo* info) { | 131 bool Compiler::MakeCodeForLiveEdit(CompilationInfo* info) { |
| 156 Handle<Context> context = Handle<Context>::null(); | 132 // Precondition: code has been parsed. Postcondition: the code field in |
| 157 Handle<Code> code = MakeCode(context, info); | 133 // the compilation info is set if compilation succeeded. |
| 134 bool succeeded = MakeCode(info); |
| 158 if (!info->shared_info().is_null()) { | 135 if (!info->shared_info().is_null()) { |
| 159 Handle<SerializedScopeInfo> scope_info = | 136 Handle<SerializedScopeInfo> scope_info = |
| 160 SerializedScopeInfo::Create(info->scope()); | 137 SerializedScopeInfo::Create(info->scope()); |
| 161 info->shared_info()->set_scope_info(*scope_info); | 138 info->shared_info()->set_scope_info(*scope_info); |
| 162 } | 139 } |
| 163 return code; | 140 return succeeded; |
| 164 } | 141 } |
| 165 #endif | 142 #endif |
| 166 | 143 |
| 167 | 144 |
| 168 static Handle<SharedFunctionInfo> MakeFunctionInfo(CompilationInfo* info, | 145 static Handle<SharedFunctionInfo> MakeFunctionInfo(CompilationInfo* info) { |
| 169 Handle<Context> context) { | |
| 170 CompilationZoneScope zone_scope(DELETE_ON_EXIT); | 146 CompilationZoneScope zone_scope(DELETE_ON_EXIT); |
| 171 | 147 |
| 172 PostponeInterruptsScope postpone; | 148 PostponeInterruptsScope postpone; |
| 173 | 149 |
| 174 ASSERT(!i::Top::global_context().is_null()); | 150 ASSERT(!i::Top::global_context().is_null()); |
| 175 Handle<Script> script = info->script(); | 151 Handle<Script> script = info->script(); |
| 176 script->set_context_data((*i::Top::global_context())->data()); | 152 script->set_context_data((*i::Top::global_context())->data()); |
| 177 | 153 |
| 178 #ifdef ENABLE_DEBUGGER_SUPPORT | 154 #ifdef ENABLE_DEBUGGER_SUPPORT |
| 179 if (info->is_eval() || info->is_json()) { | 155 if (info->is_eval() || info->is_json()) { |
| (...skipping 28 matching lines...) Expand all Loading... |
| 208 // rest of the function into account to avoid overlap with the | 184 // rest of the function into account to avoid overlap with the |
| 209 // parsing statistics. | 185 // parsing statistics. |
| 210 HistogramTimer* rate = info->is_eval() | 186 HistogramTimer* rate = info->is_eval() |
| 211 ? &Counters::compile_eval | 187 ? &Counters::compile_eval |
| 212 : &Counters::compile; | 188 : &Counters::compile; |
| 213 HistogramTimerScope timer(rate); | 189 HistogramTimerScope timer(rate); |
| 214 | 190 |
| 215 // Compile the code. | 191 // Compile the code. |
| 216 FunctionLiteral* lit = info->function(); | 192 FunctionLiteral* lit = info->function(); |
| 217 LiveEditFunctionTracker live_edit_tracker(lit); | 193 LiveEditFunctionTracker live_edit_tracker(lit); |
| 218 Handle<Code> code = MakeCode(context, info); | 194 if (!MakeCode(info)) { |
| 219 | |
| 220 // Check for stack-overflow exceptions. | |
| 221 if (code.is_null()) { | |
| 222 Top::StackOverflow(); | 195 Top::StackOverflow(); |
| 223 return Handle<SharedFunctionInfo>::null(); | 196 return Handle<SharedFunctionInfo>::null(); |
| 224 } | 197 } |
| 225 | 198 |
| 199 ASSERT(!info->code().is_null()); |
| 226 if (script->name()->IsString()) { | 200 if (script->name()->IsString()) { |
| 227 PROFILE(CodeCreateEvent( | 201 PROFILE(CodeCreateEvent( |
| 228 info->is_eval() | 202 info->is_eval() |
| 229 ? Logger::EVAL_TAG | 203 ? Logger::EVAL_TAG |
| 230 : Logger::ToNativeByScript(Logger::SCRIPT_TAG, *script), | 204 : Logger::ToNativeByScript(Logger::SCRIPT_TAG, *script), |
| 231 *code, | 205 *info->code(), |
| 232 String::cast(script->name()))); | 206 String::cast(script->name()))); |
| 233 OPROFILE(CreateNativeCodeRegion(String::cast(script->name()), | 207 OPROFILE(CreateNativeCodeRegion(String::cast(script->name()), |
| 234 code->instruction_start(), | 208 info->code()->instruction_start(), |
| 235 code->instruction_size())); | 209 info->code()->instruction_size())); |
| 236 } else { | 210 } else { |
| 237 PROFILE(CodeCreateEvent( | 211 PROFILE(CodeCreateEvent( |
| 238 info->is_eval() | 212 info->is_eval() |
| 239 ? Logger::EVAL_TAG | 213 ? Logger::EVAL_TAG |
| 240 : Logger::ToNativeByScript(Logger::SCRIPT_TAG, *script), | 214 : Logger::ToNativeByScript(Logger::SCRIPT_TAG, *script), |
| 241 *code, | 215 *info->code(), |
| 242 "")); | 216 "")); |
| 243 OPROFILE(CreateNativeCodeRegion(info->is_eval() ? "Eval" : "Script", | 217 OPROFILE(CreateNativeCodeRegion(info->is_eval() ? "Eval" : "Script", |
| 244 code->instruction_start(), | 218 info->code()->instruction_start(), |
| 245 code->instruction_size())); | 219 info->code()->instruction_size())); |
| 246 } | 220 } |
| 247 | 221 |
| 248 // Allocate function. | 222 // Allocate function. |
| 249 Handle<SharedFunctionInfo> result = | 223 Handle<SharedFunctionInfo> result = |
| 250 Factory::NewSharedFunctionInfo( | 224 Factory::NewSharedFunctionInfo( |
| 251 lit->name(), | 225 lit->name(), |
| 252 lit->materialized_literal_count(), | 226 lit->materialized_literal_count(), |
| 253 code, | 227 info->code(), |
| 254 SerializedScopeInfo::Create(info->scope())); | 228 SerializedScopeInfo::Create(info->scope())); |
| 255 | 229 |
| 256 ASSERT_EQ(RelocInfo::kNoPosition, lit->function_token_position()); | 230 ASSERT_EQ(RelocInfo::kNoPosition, lit->function_token_position()); |
| 257 Compiler::SetFunctionInfo(result, lit, true, script); | 231 Compiler::SetFunctionInfo(result, lit, true, script); |
| 258 | 232 |
| 259 // Hint to the runtime system used when allocating space for initial | 233 // Hint to the runtime system used when allocating space for initial |
| 260 // property space by setting the expected number of properties for | 234 // property space by setting the expected number of properties for |
| 261 // the instances of the function. | 235 // the instances of the function. |
| 262 SetExpectedNofPropertiesFromEstimate(result, lit->expected_property_count()); | 236 SetExpectedNofPropertiesFromEstimate(result, lit->expected_property_count()); |
| 263 | 237 |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 324 } | 298 } |
| 325 | 299 |
| 326 script->set_data(script_data.is_null() ? Heap::undefined_value() | 300 script->set_data(script_data.is_null() ? Heap::undefined_value() |
| 327 : *script_data); | 301 : *script_data); |
| 328 | 302 |
| 329 // Compile the function and add it to the cache. | 303 // Compile the function and add it to the cache. |
| 330 CompilationInfo info(script); | 304 CompilationInfo info(script); |
| 331 info.MarkAsGlobal(); | 305 info.MarkAsGlobal(); |
| 332 info.SetExtension(extension); | 306 info.SetExtension(extension); |
| 333 info.SetPreParseData(pre_data); | 307 info.SetPreParseData(pre_data); |
| 334 result = MakeFunctionInfo(&info, Handle<Context>::null()); | 308 result = MakeFunctionInfo(&info); |
| 335 if (extension == NULL && !result.is_null()) { | 309 if (extension == NULL && !result.is_null()) { |
| 336 CompilationCache::PutScript(source, result); | 310 CompilationCache::PutScript(source, result); |
| 337 } | 311 } |
| 338 | 312 |
| 339 // Get rid of the pre-parsing data (if necessary). | 313 // Get rid of the pre-parsing data (if necessary). |
| 340 if (input_pre_data == NULL && pre_data != NULL) { | 314 if (input_pre_data == NULL && pre_data != NULL) { |
| 341 delete pre_data; | 315 delete pre_data; |
| 342 } | 316 } |
| 343 } | 317 } |
| 344 | 318 |
| (...skipping 27 matching lines...) Expand all Loading... |
| 372 result = CompilationCache::LookupEval(source, context, is_global); | 346 result = CompilationCache::LookupEval(source, context, is_global); |
| 373 } | 347 } |
| 374 | 348 |
| 375 if (result.is_null()) { | 349 if (result.is_null()) { |
| 376 // Create a script object describing the script to be compiled. | 350 // Create a script object describing the script to be compiled. |
| 377 Handle<Script> script = Factory::NewScript(source); | 351 Handle<Script> script = Factory::NewScript(source); |
| 378 CompilationInfo info(script); | 352 CompilationInfo info(script); |
| 379 info.MarkAsEval(); | 353 info.MarkAsEval(); |
| 380 if (is_global) info.MarkAsGlobal(); | 354 if (is_global) info.MarkAsGlobal(); |
| 381 if (is_json) info.MarkAsJson(); | 355 if (is_json) info.MarkAsJson(); |
| 382 result = MakeFunctionInfo(&info, context); | 356 info.SetCallingContext(context); |
| 357 result = MakeFunctionInfo(&info); |
| 383 if (!result.is_null() && !is_json) { | 358 if (!result.is_null() && !is_json) { |
| 384 // For json it's unlikely that we'll ever see exactly the same string | 359 // For json it's unlikely that we'll ever see exactly the same string |
| 385 // again so we don't use the compilation cache. | 360 // again so we don't use the compilation cache. |
| 386 CompilationCache::PutEval(source, context, is_global, result); | 361 CompilationCache::PutEval(source, context, is_global, result); |
| 387 } | 362 } |
| 388 } | 363 } |
| 389 | 364 |
| 390 return result; | 365 return result; |
| 391 } | 366 } |
| 392 | 367 |
| 393 | 368 |
| 394 bool Compiler::CompileLazy(CompilationInfo* info) { | 369 bool Compiler::CompileLazy(CompilationInfo* info) { |
| 395 CompilationZoneScope zone_scope(DELETE_ON_EXIT); | 370 CompilationZoneScope zone_scope(DELETE_ON_EXIT); |
| 396 | 371 |
| 397 // The VM is in the COMPILER state until exiting this function. | 372 // The VM is in the COMPILER state until exiting this function. |
| 398 VMState state(COMPILER); | 373 VMState state(COMPILER); |
| 399 | 374 |
| 400 PostponeInterruptsScope postpone; | 375 PostponeInterruptsScope postpone; |
| 401 | 376 |
| 402 // Compute name, source code and script data. | |
| 403 Handle<SharedFunctionInfo> shared = info->shared_info(); | 377 Handle<SharedFunctionInfo> shared = info->shared_info(); |
| 404 int compiled_size = shared->end_position() - shared->start_position(); | 378 int compiled_size = shared->end_position() - shared->start_position(); |
| 405 Counters::total_compile_size.Increment(compiled_size); | 379 Counters::total_compile_size.Increment(compiled_size); |
| 406 | 380 |
| 407 // Generate the AST for the lazily compiled function. | 381 // Generate the AST for the lazily compiled function. |
| 408 if (!Parser::Parse(info)) return false; | 382 if (Parser::Parse(info)) { |
| 383 // Measure how long it takes to do the lazy compilation; only take the |
| 384 // rest of the function into account to avoid overlap with the lazy |
| 385 // parsing statistics. |
| 386 HistogramTimerScope timer(&Counters::compile_lazy); |
| 409 | 387 |
| 410 // Measure how long it takes to do the lazy compilation; only take | 388 // Compile the code. |
| 411 // the rest of the function into account to avoid overlap with the | 389 if (!MakeCode(info)) { |
| 412 // lazy parsing statistics. | 390 Top::StackOverflow(); |
| 413 HistogramTimerScope timer(&Counters::compile_lazy); | 391 } else { |
| 392 ASSERT(!info->code().is_null()); |
| 393 RecordFunctionCompilation(Logger::LAZY_COMPILE_TAG, |
| 394 Handle<String>(shared->DebugName()), |
| 395 shared->start_position(), |
| 396 info); |
| 414 | 397 |
| 415 // Compile the code. | 398 // Update the shared function info with the compiled code and the |
| 416 Handle<Code> code = MakeCode(Handle<Context>::null(), info); | 399 // scope info. Please note, that the order of the sharedfunction |
| 400 // initialization is important since SerializedScopeInfo::Create might |
| 401 // trigger a GC, causing the ASSERT below to be invalid if the code |
| 402 // was flushed. By setting the code object last we avoid this. |
| 403 Handle<SerializedScopeInfo> scope_info = |
| 404 SerializedScopeInfo::Create(info->scope()); |
| 405 shared->set_scope_info(*scope_info); |
| 406 shared->set_code(*info->code()); |
| 407 if (!info->closure().is_null()) { |
| 408 info->closure()->set_code(*info->code()); |
| 409 } |
| 417 | 410 |
| 418 // Check for stack-overflow exception. | 411 // Set the expected number of properties for instances. |
| 419 if (code.is_null()) { | 412 FunctionLiteral* lit = info->function(); |
| 420 Top::StackOverflow(); | 413 SetExpectedNofPropertiesFromEstimate(shared, |
| 421 return false; | 414 lit->expected_property_count()); |
| 415 |
| 416 // Set the optimization hints after performing lazy compilation, as |
| 417 // these are not set when the function is set up as a lazily compiled |
| 418 // function. |
| 419 shared->SetThisPropertyAssignmentsInfo( |
| 420 lit->has_only_simple_this_property_assignments(), |
| 421 *lit->this_property_assignments()); |
| 422 |
| 423 // Check the function has compiled code. |
| 424 ASSERT(shared->is_compiled()); |
| 425 shared->set_code_age(0); |
| 426 ASSERT(!info->code().is_null()); |
| 427 return true; |
| 428 } |
| 422 } | 429 } |
| 423 | 430 |
| 424 RecordFunctionCompilation(Logger::LAZY_COMPILE_TAG, | 431 ASSERT(info->code().is_null()); |
| 425 Handle<String>(String::cast(shared->name())), | 432 return false; |
| 426 Handle<String>(shared->inferred_name()), | |
| 427 shared->start_position(), | |
| 428 info->script(), | |
| 429 code); | |
| 430 | |
| 431 // Update the shared function info with the compiled code and the scope info. | |
| 432 // Please note, that the order of the sharedfunction initialization is | |
| 433 // important since SerializedScopeInfo::Create might trigger a GC, causing | |
| 434 // the ASSERT below to be invalid if the code was flushed. By setting the code | |
| 435 // object last we avoid this. | |
| 436 Handle<SerializedScopeInfo> scope_info = | |
| 437 SerializedScopeInfo::Create(info->scope()); | |
| 438 shared->set_scope_info(*scope_info); | |
| 439 shared->set_code(*code); | |
| 440 if (!info->closure().is_null()) { | |
| 441 info->closure()->set_code(*code); | |
| 442 } | |
| 443 | |
| 444 // Set the expected number of properties for instances. | |
| 445 FunctionLiteral* lit = info->function(); | |
| 446 SetExpectedNofPropertiesFromEstimate(shared, lit->expected_property_count()); | |
| 447 | |
| 448 // Set the optimication hints after performing lazy compilation, as these are | |
| 449 // not set when the function is set up as a lazily compiled function. | |
| 450 shared->SetThisPropertyAssignmentsInfo( | |
| 451 lit->has_only_simple_this_property_assignments(), | |
| 452 *lit->this_property_assignments()); | |
| 453 | |
| 454 // Check the function has compiled code. | |
| 455 ASSERT(shared->is_compiled()); | |
| 456 shared->set_code_age(0); | |
| 457 return true; | |
| 458 } | 433 } |
| 459 | 434 |
| 460 | 435 |
| 461 Handle<SharedFunctionInfo> Compiler::BuildFunctionInfo(FunctionLiteral* literal, | 436 Handle<SharedFunctionInfo> Compiler::BuildFunctionInfo(FunctionLiteral* literal, |
| 462 Handle<Script> script, | 437 Handle<Script> script) { |
| 463 AstVisitor* caller) { | |
| 464 LiveEditFunctionTracker live_edit_tracker(literal); | |
| 465 #ifdef DEBUG | 438 #ifdef DEBUG |
| 466 // We should not try to compile the same function literal more than | 439 // We should not try to compile the same function literal more than |
| 467 // once. | 440 // once. |
| 468 literal->mark_as_compiled(); | 441 literal->mark_as_compiled(); |
| 469 #endif | 442 #endif |
| 470 | 443 |
| 471 // Determine if the function can be lazily compiled. This is | 444 // Precondition: code has been parsed and scopes have been analyzed. |
| 472 // necessary to allow some of our builtin JS files to be lazily | 445 CompilationInfo info(script); |
| 473 // compiled. These builtins cannot be handled lazily by the parser, | 446 info.SetFunction(literal); |
| 474 // since we have to know if a function uses the special natives | 447 info.SetScope(literal->scope()); |
| 475 // syntax, which is something the parser records. | 448 |
| 449 LiveEditFunctionTracker live_edit_tracker(literal); |
| 450 // Determine if the function can be lazily compiled. This is necessary to |
| 451 // allow some of our builtin JS files to be lazily compiled. These |
| 452 // builtins cannot be handled lazily by the parser, since we have to know |
| 453 // if a function uses the special natives syntax, which is something the |
| 454 // parser records. |
| 476 bool allow_lazy = literal->AllowsLazyCompilation() && | 455 bool allow_lazy = literal->AllowsLazyCompilation() && |
| 477 !LiveEditFunctionTracker::IsActive(); | 456 !LiveEditFunctionTracker::IsActive(); |
| 478 | 457 |
| 479 Handle<SerializedScopeInfo> scope_info(SerializedScopeInfo::Empty()); | 458 Handle<SerializedScopeInfo> scope_info(SerializedScopeInfo::Empty()); |
| 480 | 459 |
| 481 // Generate code | 460 // Generate code |
| 482 Handle<Code> code; | |
| 483 if (FLAG_lazy && allow_lazy) { | 461 if (FLAG_lazy && allow_lazy) { |
| 484 code = Handle<Code>(Builtins::builtin(Builtins::LazyCompile)); | 462 Handle<Code> code(Builtins::builtin(Builtins::LazyCompile)); |
| 463 info.SetCode(code); |
| 485 } else { | 464 } else { |
| 486 // The bodies of function literals have not yet been visited by | |
| 487 // the AST optimizer/analyzer. | |
| 488 if (!Rewriter::Optimize(literal)) { | |
| 489 return Handle<SharedFunctionInfo>::null(); | |
| 490 } | |
| 491 | |
| 492 // Generate code and return it. The way that the compilation mode | 465 // Generate code and return it. The way that the compilation mode |
| 493 // is controlled by the command-line flags is described in | 466 // is controlled by the command-line flags is described in |
| 494 // the static helper function MakeCode. | 467 // the static helper function MakeCode. |
| 495 CompilationInfo info(script); | 468 // |
| 496 info.SetFunction(literal); | 469 // The bodies of function literals have not yet been visited by |
| 470 // the AST analyzer. |
| 471 if (!Rewriter::Analyze(&info)) return Handle<SharedFunctionInfo>::null(); |
| 497 | 472 |
| 498 bool is_run_once = literal->try_full_codegen(); | 473 bool is_run_once = literal->try_full_codegen(); |
| 499 bool use_full = FLAG_full_compiler && !literal->contains_loops(); | 474 bool use_full = FLAG_full_compiler && !literal->contains_loops(); |
| 500 if (AlwaysFullCompiler() || (use_full && is_run_once)) { | 475 if (AlwaysFullCompiler() || (use_full && is_run_once)) { |
| 501 code = FullCodeGenerator::MakeCode(&info); | 476 if (!FullCodeGenerator::MakeCode(&info)) { |
| 477 return Handle<SharedFunctionInfo>::null(); |
| 478 } |
| 502 } else { | 479 } else { |
| 503 // We fall back to the classic V8 code generator. | 480 // We fall back to the classic V8 code generator. |
| 504 AssignedVariablesAnalyzer ava(literal); | 481 AssignedVariablesAnalyzer ava; |
| 505 if (!ava.Analyze()) return Handle<SharedFunctionInfo>::null(); | 482 if (!ava.Analyze(&info)) return Handle<SharedFunctionInfo>::null(); |
| 506 code = CodeGenerator::MakeCode(&info); | 483 if (!CodeGenerator::MakeCode(&info)) { |
| 507 } | 484 return Handle<SharedFunctionInfo>::null(); |
| 508 | 485 } |
| 509 // Check for stack-overflow exception. | |
| 510 if (code.is_null()) { | |
| 511 caller->SetStackOverflow(); | |
| 512 return Handle<SharedFunctionInfo>::null(); | |
| 513 } | 486 } |
| 514 | 487 |
| 515 // Function compilation complete. | 488 // Function compilation complete. |
| 516 RecordFunctionCompilation(Logger::FUNCTION_TAG, | 489 RecordFunctionCompilation(Logger::FUNCTION_TAG, |
| 517 literal->name(), | 490 literal->debug_name(), |
| 518 literal->inferred_name(), | |
| 519 literal->start_position(), | 491 literal->start_position(), |
| 520 script, | 492 &info); |
| 521 code); | |
| 522 scope_info = SerializedScopeInfo::Create(info.scope()); | 493 scope_info = SerializedScopeInfo::Create(info.scope()); |
| 523 } | 494 } |
| 524 | 495 |
| 525 // Create a shared function info object. | 496 // Create a shared function info object. |
| 526 Handle<SharedFunctionInfo> result = | 497 Handle<SharedFunctionInfo> result = |
| 527 Factory::NewSharedFunctionInfo(literal->name(), | 498 Factory::NewSharedFunctionInfo(literal->name(), |
| 528 literal->materialized_literal_count(), | 499 literal->materialized_literal_count(), |
| 529 code, | 500 info.code(), |
| 530 scope_info); | 501 scope_info); |
| 531 SetFunctionInfo(result, literal, false, script); | 502 SetFunctionInfo(result, literal, false, script); |
| 532 | 503 |
| 533 // Set the expected number of properties for instances and return | 504 // Set the expected number of properties for instances and return |
| 534 // the resulting function. | 505 // the resulting function. |
| 535 SetExpectedNofPropertiesFromEstimate(result, | 506 SetExpectedNofPropertiesFromEstimate(result, |
| 536 literal->expected_property_count()); | 507 literal->expected_property_count()); |
| 537 live_edit_tracker.RecordFunctionInfo(result, literal); | 508 live_edit_tracker.RecordFunctionInfo(result, literal); |
| 538 return result; | 509 return result; |
| 539 } | 510 } |
| (...skipping 19 matching lines...) Expand all Loading... |
| 559 function_info->SetThisPropertyAssignmentsInfo( | 530 function_info->SetThisPropertyAssignmentsInfo( |
| 560 lit->has_only_simple_this_property_assignments(), | 531 lit->has_only_simple_this_property_assignments(), |
| 561 *lit->this_property_assignments()); | 532 *lit->this_property_assignments()); |
| 562 function_info->set_try_full_codegen(lit->try_full_codegen()); | 533 function_info->set_try_full_codegen(lit->try_full_codegen()); |
| 563 function_info->set_allows_lazy_compilation(lit->AllowsLazyCompilation()); | 534 function_info->set_allows_lazy_compilation(lit->AllowsLazyCompilation()); |
| 564 } | 535 } |
| 565 | 536 |
| 566 | 537 |
| 567 void Compiler::RecordFunctionCompilation(Logger::LogEventsAndTags tag, | 538 void Compiler::RecordFunctionCompilation(Logger::LogEventsAndTags tag, |
| 568 Handle<String> name, | 539 Handle<String> name, |
| 569 Handle<String> inferred_name, | |
| 570 int start_position, | 540 int start_position, |
| 571 Handle<Script> script, | 541 CompilationInfo* info) { |
| 572 Handle<Code> code) { | 542 // Log the code generation. If source information is available include |
| 573 // Log the code generation. If source information is available | 543 // script name and line number. Check explicitly whether logging is |
| 574 // include script name and line number. Check explicitly whether | 544 // enabled as finding the line number is not free. |
| 575 // logging is enabled as finding the line number is not free. | 545 if (Logger::is_logging() || |
| 576 if (Logger::is_logging() | 546 OProfileAgent::is_enabled() || |
| 577 || OProfileAgent::is_enabled() | 547 CpuProfiler::is_profiling()) { |
| 578 || CpuProfiler::is_profiling()) { | 548 Handle<Script> script = info->script(); |
| 579 Handle<String> func_name(name->length() > 0 ? *name : *inferred_name); | 549 Handle<Code> code = info->code(); |
| 580 if (script->name()->IsString()) { | 550 if (script->name()->IsString()) { |
| 581 int line_num = GetScriptLineNumber(script, start_position) + 1; | 551 int line_num = GetScriptLineNumber(script, start_position) + 1; |
| 582 USE(line_num); | 552 USE(line_num); |
| 583 PROFILE(CodeCreateEvent(Logger::ToNativeByScript(tag, *script), | 553 PROFILE(CodeCreateEvent(Logger::ToNativeByScript(tag, *script), |
| 584 *code, *func_name, | 554 *code, |
| 585 String::cast(script->name()), line_num)); | 555 *name, |
| 586 OPROFILE(CreateNativeCodeRegion(*func_name, | 556 String::cast(script->name()), |
| 557 line_num)); |
| 558 OPROFILE(CreateNativeCodeRegion(*name, |
| 587 String::cast(script->name()), | 559 String::cast(script->name()), |
| 588 line_num, | 560 line_num, |
| 589 code->instruction_start(), | 561 code->instruction_start(), |
| 590 code->instruction_size())); | 562 code->instruction_size())); |
| 591 } else { | 563 } else { |
| 592 PROFILE(CodeCreateEvent(Logger::ToNativeByScript(tag, *script), | 564 PROFILE(CodeCreateEvent(Logger::ToNativeByScript(tag, *script), |
| 593 *code, *func_name)); | 565 *code, |
| 594 OPROFILE(CreateNativeCodeRegion(*func_name, | 566 *name)); |
| 567 OPROFILE(CreateNativeCodeRegion(*name, |
| 595 code->instruction_start(), | 568 code->instruction_start(), |
| 596 code->instruction_size())); | 569 code->instruction_size())); |
| 597 } | 570 } |
| 598 } | 571 } |
| 599 } | 572 } |
| 600 | 573 |
| 601 } } // namespace v8::internal | 574 } } // namespace v8::internal |
| OLD | NEW |