Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(80)

Side by Side Diff: src/compiler.cc

Issue 6697023: Merge 6800:7180 from the bleeding edge branch to the experimental/gc branch. (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/gc/
Patch Set: Created 9 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/compiler.h ('k') | src/cpu-profiler.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 154 matching lines...) Expand 10 before | Expand all | Expand 10 after
165 // non-optimizable information for the code. When the code is 165 // non-optimizable information for the code. When the code is
166 // regenerated and set on the shared function info it is marked as 166 // regenerated and set on the shared function info it is marked as
167 // non-optimizable if optimization is disabled for the shared 167 // non-optimizable if optimization is disabled for the shared
168 // function info. 168 // function info.
169 Handle<SharedFunctionInfo> shared = info->shared_info(); 169 Handle<SharedFunctionInfo> shared = info->shared_info();
170 shared->set_optimization_disabled(true); 170 shared->set_optimization_disabled(true);
171 Handle<Code> code = Handle<Code>(shared->code()); 171 Handle<Code> code = Handle<Code>(shared->code());
172 ASSERT(code->kind() == Code::FUNCTION); 172 ASSERT(code->kind() == Code::FUNCTION);
173 code->set_optimizable(false); 173 code->set_optimizable(false);
174 info->SetCode(code); 174 info->SetCode(code);
175 CompilationCache::MarkForLazyOptimizing(info->closure());
175 if (FLAG_trace_opt) { 176 if (FLAG_trace_opt) {
176 PrintF("[disabled optimization for: "); 177 PrintF("[disabled optimization for: ");
177 info->closure()->PrintName(); 178 info->closure()->PrintName();
178 PrintF(" / %" V8PRIxPTR "]\n", 179 PrintF(" / %" V8PRIxPTR "]\n",
179 reinterpret_cast<intptr_t>(*info->closure())); 180 reinterpret_cast<intptr_t>(*info->closure()));
180 } 181 }
181 } 182 }
182 183
183 184
184 static bool MakeCrankshaftCode(CompilationInfo* info) { 185 static bool MakeCrankshaftCode(CompilationInfo* info) {
(...skipping 29 matching lines...) Expand all
214 // True indicates the compilation pipeline is still going, not 215 // True indicates the compilation pipeline is still going, not
215 // necessarily that we optimized the code. 216 // necessarily that we optimized the code.
216 return true; 217 return true;
217 } 218 }
218 219
219 // Due to an encoding limit on LUnallocated operands in the Lithium 220 // Due to an encoding limit on LUnallocated operands in the Lithium
220 // language, we cannot optimize functions with too many formal parameters 221 // language, we cannot optimize functions with too many formal parameters
221 // or perform on-stack replacement for function with too many 222 // or perform on-stack replacement for function with too many
222 // stack-allocated local variables. 223 // stack-allocated local variables.
223 // 224 //
224 // The encoding is as a signed value, with parameters using the negative 225 // The encoding is as a signed value, with parameters and receiver using
225 // indices and locals the non-negative ones. 226 // the negative indices and locals the non-negative ones.
226 const int limit = LUnallocated::kMaxFixedIndices / 2; 227 const int limit = LUnallocated::kMaxFixedIndices / 2;
227 Scope* scope = info->scope(); 228 Scope* scope = info->scope();
228 if (scope->num_parameters() > limit || scope->num_stack_slots() > limit) { 229 if ((scope->num_parameters() + 1) > limit ||
230 scope->num_stack_slots() > limit) {
229 AbortAndDisable(info); 231 AbortAndDisable(info);
230 // True indicates the compilation pipeline is still going, not 232 // True indicates the compilation pipeline is still going, not
231 // necessarily that we optimized the code. 233 // necessarily that we optimized the code.
232 return true; 234 return true;
233 } 235 }
234 236
235 // Take --hydrogen-filter into account. 237 // Take --hydrogen-filter into account.
236 Vector<const char> filter = CStrVector(FLAG_hydrogen_filter); 238 Vector<const char> filter = CStrVector(FLAG_hydrogen_filter);
237 Handle<String> name = info->function()->debug_name(); 239 Handle<String> name = info->function()->debug_name();
238 bool match = filter.is_empty() || name->IsEqualTo(filter); 240 bool match = filter.is_empty() || name->IsEqualTo(filter);
239 if (!match) { 241 if (!match) {
240 info->SetCode(code); 242 info->SetCode(code);
241 return true; 243 return true;
242 } 244 }
243 245
244 // Recompile the unoptimized version of the code if the current version 246 // Recompile the unoptimized version of the code if the current version
245 // doesn't have deoptimization support. Alternatively, we may decide to 247 // doesn't have deoptimization support. Alternatively, we may decide to
246 // run the full code generator to get a baseline for the compile-time 248 // run the full code generator to get a baseline for the compile-time
247 // performance of the hydrogen-based compiler. 249 // performance of the hydrogen-based compiler.
248 int64_t start = OS::Ticks(); 250 int64_t start = OS::Ticks();
249 bool should_recompile = !info->shared_info()->has_deoptimization_support(); 251 bool should_recompile = !info->shared_info()->has_deoptimization_support();
250 if (should_recompile || FLAG_time_hydrogen) { 252 if (should_recompile || FLAG_hydrogen_stats) {
251 HPhase phase(HPhase::kFullCodeGen); 253 HPhase phase(HPhase::kFullCodeGen);
252 CompilationInfo unoptimized(info->shared_info()); 254 CompilationInfo unoptimized(info->shared_info());
253 // Note that we use the same AST that we will use for generating the 255 // Note that we use the same AST that we will use for generating the
254 // optimized code. 256 // optimized code.
255 unoptimized.SetFunction(info->function()); 257 unoptimized.SetFunction(info->function());
256 unoptimized.SetScope(info->scope()); 258 unoptimized.SetScope(info->scope());
257 if (should_recompile) unoptimized.EnableDeoptimizationSupport(); 259 if (should_recompile) unoptimized.EnableDeoptimizationSupport();
258 bool succeeded = FullCodeGenerator::MakeCode(&unoptimized); 260 bool succeeded = FullCodeGenerator::MakeCode(&unoptimized);
259 if (should_recompile) { 261 if (should_recompile) {
260 if (!succeeded) return false; 262 if (!succeeded) return false;
261 Handle<SharedFunctionInfo> shared = info->shared_info(); 263 Handle<SharedFunctionInfo> shared = info->shared_info();
262 shared->EnableDeoptimizationSupport(*unoptimized.code()); 264 shared->EnableDeoptimizationSupport(*unoptimized.code());
263 // The existing unoptimized code was replaced with the new one. 265 // The existing unoptimized code was replaced with the new one.
264 Compiler::RecordFunctionCompilation(Logger::LAZY_COMPILE_TAG, 266 Compiler::RecordFunctionCompilation(
265 Handle<String>(shared->DebugName()), 267 Logger::LAZY_COMPILE_TAG, &unoptimized, shared);
266 shared->start_position(),
267 &unoptimized);
268 } 268 }
269 } 269 }
270 270
271 // Check that the unoptimized, shared code is ready for 271 // Check that the unoptimized, shared code is ready for
272 // optimizations. When using the always_opt flag we disregard the 272 // optimizations. When using the always_opt flag we disregard the
273 // optimizable marker in the code object and optimize anyway. This 273 // optimizable marker in the code object and optimize anyway. This
274 // is safe as long as the unoptimized code has deoptimization 274 // is safe as long as the unoptimized code has deoptimization
275 // support. 275 // support.
276 ASSERT(FLAG_always_opt || info->shared_info()->code()->optimizable()); 276 ASSERT(FLAG_always_opt || code->optimizable());
277 ASSERT(info->shared_info()->has_deoptimization_support()); 277 ASSERT(info->shared_info()->has_deoptimization_support());
278 278
279 if (FLAG_trace_hydrogen) { 279 if (FLAG_trace_hydrogen) {
280 PrintF("-----------------------------------------------------------\n"); 280 PrintF("-----------------------------------------------------------\n");
281 PrintF("Compiling method %s using hydrogen\n", *name->ToCString()); 281 PrintF("Compiling method %s using hydrogen\n", *name->ToCString());
282 HTracer::Instance()->TraceCompilation(info->function()); 282 HTracer::Instance()->TraceCompilation(info->function());
283 } 283 }
284 284
285 TypeFeedbackOracle oracle( 285 Handle<Context> global_context(info->closure()->context()->global_context());
286 Handle<Code>(info->shared_info()->code()), 286 TypeFeedbackOracle oracle(code, global_context);
287 Handle<Context>(info->closure()->context()->global_context())); 287 HGraphBuilder builder(info, &oracle);
288 HGraphBuilder builder(&oracle);
289 HPhase phase(HPhase::kTotal); 288 HPhase phase(HPhase::kTotal);
290 HGraph* graph = builder.CreateGraph(info); 289 HGraph* graph = builder.CreateGraph();
291 if (Top::has_pending_exception()) { 290 if (Top::has_pending_exception()) {
292 info->SetCode(Handle<Code>::null()); 291 info->SetCode(Handle<Code>::null());
293 return false; 292 return false;
294 } 293 }
295 294
296 if (graph != NULL && FLAG_build_lithium) { 295 if (graph != NULL && FLAG_build_lithium) {
297 Handle<Code> code = graph->Compile(); 296 Handle<Code> optimized_code = graph->Compile(info);
298 if (!code.is_null()) { 297 if (!optimized_code.is_null()) {
299 info->SetCode(code); 298 info->SetCode(optimized_code);
300 FinishOptimization(info->closure(), start); 299 FinishOptimization(info->closure(), start);
301 return true; 300 return true;
302 } 301 }
303 } 302 }
304 303
305 // Compilation with the Hydrogen compiler failed. Keep using the 304 // Compilation with the Hydrogen compiler failed. Keep using the
306 // shared code but mark it as unoptimizable. 305 // shared code but mark it as unoptimizable.
307 AbortAndDisable(info); 306 AbortAndDisable(info);
308 // True indicates the compilation pipeline is still going, not necessarily 307 // True indicates the compilation pipeline is still going, not necessarily
309 // that we optimized the code. 308 // that we optimized the code.
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
408 HistogramTimerScope timer(rate); 407 HistogramTimerScope timer(rate);
409 408
410 // Compile the code. 409 // Compile the code.
411 FunctionLiteral* lit = info->function(); 410 FunctionLiteral* lit = info->function();
412 LiveEditFunctionTracker live_edit_tracker(lit); 411 LiveEditFunctionTracker live_edit_tracker(lit);
413 if (!MakeCode(info)) { 412 if (!MakeCode(info)) {
414 Top::StackOverflow(); 413 Top::StackOverflow();
415 return Handle<SharedFunctionInfo>::null(); 414 return Handle<SharedFunctionInfo>::null();
416 } 415 }
417 416
417 // Allocate function.
418 ASSERT(!info->code().is_null()); 418 ASSERT(!info->code().is_null());
419 Handle<SharedFunctionInfo> result =
420 Factory::NewSharedFunctionInfo(
421 lit->name(),
422 lit->materialized_literal_count(),
423 info->code(),
424 SerializedScopeInfo::Create(info->scope()));
425
426 ASSERT_EQ(RelocInfo::kNoPosition, lit->function_token_position());
427 Compiler::SetFunctionInfo(result, lit, true, script);
428
419 if (script->name()->IsString()) { 429 if (script->name()->IsString()) {
420 PROFILE(CodeCreateEvent( 430 PROFILE(CodeCreateEvent(
421 info->is_eval() 431 info->is_eval()
422 ? Logger::EVAL_TAG 432 ? Logger::EVAL_TAG
423 : Logger::ToNativeByScript(Logger::SCRIPT_TAG, *script), 433 : Logger::ToNativeByScript(Logger::SCRIPT_TAG, *script),
424 *info->code(), 434 *info->code(),
435 *result,
425 String::cast(script->name()))); 436 String::cast(script->name())));
426 GDBJIT(AddCode(Handle<String>(String::cast(script->name())), 437 GDBJIT(AddCode(Handle<String>(String::cast(script->name())),
427 script, 438 script,
428 info->code())); 439 info->code()));
429 } else { 440 } else {
430 PROFILE(CodeCreateEvent( 441 PROFILE(CodeCreateEvent(
431 info->is_eval() 442 info->is_eval()
432 ? Logger::EVAL_TAG 443 ? Logger::EVAL_TAG
433 : Logger::ToNativeByScript(Logger::SCRIPT_TAG, *script), 444 : Logger::ToNativeByScript(Logger::SCRIPT_TAG, *script),
434 *info->code(), 445 *info->code(),
435 "")); 446 *result,
447 Heap::empty_string()));
436 GDBJIT(AddCode(Handle<String>(), script, info->code())); 448 GDBJIT(AddCode(Handle<String>(), script, info->code()));
437 } 449 }
438 450
439 // Allocate function.
440 Handle<SharedFunctionInfo> result =
441 Factory::NewSharedFunctionInfo(
442 lit->name(),
443 lit->materialized_literal_count(),
444 info->code(),
445 SerializedScopeInfo::Create(info->scope()));
446
447 ASSERT_EQ(RelocInfo::kNoPosition, lit->function_token_position());
448 Compiler::SetFunctionInfo(result, lit, true, script);
449
450 // Hint to the runtime system used when allocating space for initial 451 // Hint to the runtime system used when allocating space for initial
451 // property space by setting the expected number of properties for 452 // property space by setting the expected number of properties for
452 // the instances of the function. 453 // the instances of the function.
453 SetExpectedNofPropertiesFromEstimate(result, lit->expected_property_count()); 454 SetExpectedNofPropertiesFromEstimate(result, lit->expected_property_count());
454 455
455 #ifdef ENABLE_DEBUGGER_SUPPORT 456 #ifdef ENABLE_DEBUGGER_SUPPORT
456 // Notify debugger 457 // Notify debugger
457 Debugger::OnAfterCompile(script, Debugger::NO_AFTER_COMPILE_FLAGS); 458 Debugger::OnAfterCompile(script, Debugger::NO_AFTER_COMPILE_FLAGS);
458 #endif 459 #endif
459 460
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
521 } 522 }
522 523
523 script->set_data(script_data.is_null() ? Heap::undefined_value() 524 script->set_data(script_data.is_null() ? Heap::undefined_value()
524 : *script_data); 525 : *script_data);
525 526
526 // Compile the function and add it to the cache. 527 // Compile the function and add it to the cache.
527 CompilationInfo info(script); 528 CompilationInfo info(script);
528 info.MarkAsGlobal(); 529 info.MarkAsGlobal();
529 info.SetExtension(extension); 530 info.SetExtension(extension);
530 info.SetPreParseData(pre_data); 531 info.SetPreParseData(pre_data);
532 if (natives == NATIVES_CODE) info.MarkAsAllowingNativesSyntax();
531 result = MakeFunctionInfo(&info); 533 result = MakeFunctionInfo(&info);
532 if (extension == NULL && !result.is_null()) { 534 if (extension == NULL && !result.is_null()) {
533 CompilationCache::PutScript(source, result); 535 CompilationCache::PutScript(source, result);
534 } 536 }
535 537
536 // Get rid of the pre-parsing data (if necessary). 538 // Get rid of the pre-parsing data (if necessary).
537 if (input_pre_data == NULL && pre_data != NULL) { 539 if (input_pre_data == NULL && pre_data != NULL) {
538 delete pre_data; 540 delete pre_data;
539 } 541 }
540 } 542 }
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
606 608
607 // Compile the code. 609 // Compile the code.
608 if (!MakeCode(info)) { 610 if (!MakeCode(info)) {
609 if (!Top::has_pending_exception()) { 611 if (!Top::has_pending_exception()) {
610 Top::StackOverflow(); 612 Top::StackOverflow();
611 } 613 }
612 } else { 614 } else {
613 ASSERT(!info->code().is_null()); 615 ASSERT(!info->code().is_null());
614 Handle<Code> code = info->code(); 616 Handle<Code> code = info->code();
615 Handle<JSFunction> function = info->closure(); 617 Handle<JSFunction> function = info->closure();
616 RecordFunctionCompilation(Logger::LAZY_COMPILE_TAG, 618 RecordFunctionCompilation(Logger::LAZY_COMPILE_TAG, info, shared);
617 Handle<String>(shared->DebugName()),
618 shared->start_position(),
619 info);
620 619
621 if (info->IsOptimizing()) { 620 if (info->IsOptimizing()) {
622 function->ReplaceCode(*code); 621 function->ReplaceCode(*code);
623 } else { 622 } else {
624 // Update the shared function info with the compiled code and the 623 // Update the shared function info with the compiled code and the
625 // scope info. Please note, that the order of the shared function 624 // scope info. Please note, that the order of the shared function
626 // info initialization is important since set_scope_info might 625 // info initialization is important since set_scope_info might
627 // trigger a GC, causing the ASSERT below to be invalid if the code 626 // trigger a GC, causing the ASSERT below to be invalid if the code
628 // was flushed. By settting the code object last we avoid this. 627 // was flushed. By settting the code object last we avoid this.
629 Handle<SerializedScopeInfo> scope_info = 628 Handle<SerializedScopeInfo> scope_info =
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
717 // We fall back to the classic V8 code generator. 716 // We fall back to the classic V8 code generator.
718 if (!AssignedVariablesAnalyzer::Analyze(&info) || 717 if (!AssignedVariablesAnalyzer::Analyze(&info) ||
719 !CodeGenerator::MakeCode(&info)) { 718 !CodeGenerator::MakeCode(&info)) {
720 return Handle<SharedFunctionInfo>::null(); 719 return Handle<SharedFunctionInfo>::null();
721 } 720 }
722 } 721 }
723 } 722 }
724 ASSERT(!info.code().is_null()); 723 ASSERT(!info.code().is_null());
725 724
726 // Function compilation complete. 725 // Function compilation complete.
727 RecordFunctionCompilation(Logger::FUNCTION_TAG,
728 literal->debug_name(),
729 literal->start_position(),
730 &info);
731 scope_info = SerializedScopeInfo::Create(info.scope()); 726 scope_info = SerializedScopeInfo::Create(info.scope());
732 } 727 }
733 728
734 // Create a shared function info object. 729 // Create a shared function info object.
735 Handle<SharedFunctionInfo> result = 730 Handle<SharedFunctionInfo> result =
736 Factory::NewSharedFunctionInfo(literal->name(), 731 Factory::NewSharedFunctionInfo(literal->name(),
737 literal->materialized_literal_count(), 732 literal->materialized_literal_count(),
738 info.code(), 733 info.code(),
739 scope_info); 734 scope_info);
740 SetFunctionInfo(result, literal, false, script); 735 SetFunctionInfo(result, literal, false, script);
736 RecordFunctionCompilation(Logger::FUNCTION_TAG, &info, result);
741 result->set_allows_lazy_compilation(allow_lazy); 737 result->set_allows_lazy_compilation(allow_lazy);
742 738
743 // Set the expected number of properties for instances and return 739 // Set the expected number of properties for instances and return
744 // the resulting function. 740 // the resulting function.
745 SetExpectedNofPropertiesFromEstimate(result, 741 SetExpectedNofPropertiesFromEstimate(result,
746 literal->expected_property_count()); 742 literal->expected_property_count());
747 live_edit_tracker.RecordFunctionInfo(result, literal); 743 live_edit_tracker.RecordFunctionInfo(result, literal);
748 return result; 744 return result;
749 } 745 }
750 746
(...skipping 18 matching lines...) Expand all
769 function_info->SetThisPropertyAssignmentsInfo( 765 function_info->SetThisPropertyAssignmentsInfo(
770 lit->has_only_simple_this_property_assignments(), 766 lit->has_only_simple_this_property_assignments(),
771 *lit->this_property_assignments()); 767 *lit->this_property_assignments());
772 function_info->set_try_full_codegen(lit->try_full_codegen()); 768 function_info->set_try_full_codegen(lit->try_full_codegen());
773 function_info->set_allows_lazy_compilation(lit->AllowsLazyCompilation()); 769 function_info->set_allows_lazy_compilation(lit->AllowsLazyCompilation());
774 function_info->set_strict_mode(lit->strict_mode()); 770 function_info->set_strict_mode(lit->strict_mode());
775 } 771 }
776 772
777 773
778 void Compiler::RecordFunctionCompilation(Logger::LogEventsAndTags tag, 774 void Compiler::RecordFunctionCompilation(Logger::LogEventsAndTags tag,
779 Handle<String> name, 775 CompilationInfo* info,
780 int start_position, 776 Handle<SharedFunctionInfo> shared) {
781 CompilationInfo* info) { 777 // SharedFunctionInfo is passed separately, because if CompilationInfo
778 // was created using Script object, it will not have it.
779
782 // Log the code generation. If source information is available include 780 // Log the code generation. If source information is available include
783 // script name and line number. Check explicitly whether logging is 781 // script name and line number. Check explicitly whether logging is
784 // enabled as finding the line number is not free. 782 // enabled as finding the line number is not free.
785 if (Logger::is_logging() || 783 if (Logger::is_logging() || CpuProfiler::is_profiling()) {
786 CpuProfiler::is_profiling()) {
787 Handle<Script> script = info->script(); 784 Handle<Script> script = info->script();
788 Handle<Code> code = info->code(); 785 Handle<Code> code = info->code();
786 if (*code == Builtins::builtin(Builtins::LazyCompile)) return;
789 if (script->name()->IsString()) { 787 if (script->name()->IsString()) {
790 int line_num = GetScriptLineNumber(script, start_position) + 1; 788 int line_num = GetScriptLineNumber(script, shared->start_position()) + 1;
791 USE(line_num); 789 USE(line_num);
792 PROFILE(CodeCreateEvent(Logger::ToNativeByScript(tag, *script), 790 PROFILE(CodeCreateEvent(Logger::ToNativeByScript(tag, *script),
793 *code, 791 *code,
794 *name, 792 *shared,
795 String::cast(script->name()), 793 String::cast(script->name()),
796 line_num)); 794 line_num));
797 } else { 795 } else {
798 PROFILE(CodeCreateEvent(Logger::ToNativeByScript(tag, *script), 796 PROFILE(CodeCreateEvent(Logger::ToNativeByScript(tag, *script),
799 *code, 797 *code,
800 *name)); 798 *shared,
799 shared->DebugName()));
801 } 800 }
802 } 801 }
803 802
804 GDBJIT(AddCode(name, 803 GDBJIT(AddCode(name,
805 Handle<Script>(info->script()), 804 Handle<Script>(info->script()),
806 Handle<Code>(info->code()))); 805 Handle<Code>(info->code())));
807 } 806 }
808 807
809 } } // namespace v8::internal 808 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/compiler.h ('k') | src/cpu-profiler.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698