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 |