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

Side by Side Diff: src/hydrogen.cc

Issue 6628012: Refactor polymorphic load and inline function graph construction. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
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/hydrogen.h ('k') | src/ia32/lithium-codegen-ia32.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 2011 the V8 project authors. All rights reserved. 1 // Copyright 2011 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 518 matching lines...) Expand 10 before | Expand all | Expand 10 after
529 529
530 void HBasicBlock::FinishExit(HControlInstruction* instruction) { 530 void HBasicBlock::FinishExit(HControlInstruction* instruction) {
531 Finish(instruction); 531 Finish(instruction);
532 ClearEnvironment(); 532 ClearEnvironment();
533 } 533 }
534 534
535 535
536 HGraph::HGraph(CompilationInfo* info) 536 HGraph::HGraph(CompilationInfo* info)
537 : HSubgraph(this), 537 : HSubgraph(this),
538 next_block_id_(0), 538 next_block_id_(0),
539 info_(info),
540 blocks_(8), 539 blocks_(8),
541 values_(16), 540 values_(16),
542 phi_list_(NULL) { 541 phi_list_(NULL) {
543 start_environment_ = new HEnvironment(NULL, info->scope(), info->closure()); 542 start_environment_ = new HEnvironment(NULL, info->scope(), info->closure());
544 start_environment_->set_ast_id(info->function()->id()); 543 start_environment_->set_ast_id(info->function()->id());
545 } 544 }
546 545
547 546
548 bool HGraph::AllowCodeMotion() const { 547 Handle<Code> HGraph::Compile(CompilationInfo* info) {
549 return info()->shared_info()->opt_count() + 1 < Compiler::kDefaultMaxOptCount;
550 }
551
552
553 Handle<Code> HGraph::Compile() {
554 int values = GetMaximumValueID(); 548 int values = GetMaximumValueID();
555 if (values > LAllocator::max_initial_value_ids()) { 549 if (values > LAllocator::max_initial_value_ids()) {
556 if (FLAG_trace_bailout) PrintF("Function is too big\n"); 550 if (FLAG_trace_bailout) PrintF("Function is too big\n");
557 return Handle<Code>::null(); 551 return Handle<Code>::null();
558 } 552 }
559 553
560 LAllocator allocator(values, this); 554 LAllocator allocator(values, this);
561 LChunkBuilder builder(this, &allocator); 555 LChunkBuilder builder(info, this, &allocator);
562 LChunk* chunk = builder.Build(); 556 LChunk* chunk = builder.Build();
563 if (chunk == NULL) return Handle<Code>::null(); 557 if (chunk == NULL) return Handle<Code>::null();
564 558
565 if (!FLAG_alloc_lithium) return Handle<Code>::null(); 559 if (!FLAG_alloc_lithium) return Handle<Code>::null();
566 560
567 allocator.Allocate(chunk); 561 allocator.Allocate(chunk);
568 562
569 if (!FLAG_use_lithium) return Handle<Code>::null(); 563 if (!FLAG_use_lithium) return Handle<Code>::null();
570 564
571 MacroAssembler assembler(NULL, 0); 565 MacroAssembler assembler(NULL, 0);
572 LCodeGen generator(chunk, &assembler, info()); 566 LCodeGen generator(chunk, &assembler, info);
573 567
574 if (FLAG_eliminate_empty_blocks) { 568 if (FLAG_eliminate_empty_blocks) {
575 chunk->MarkEmptyBlocks(); 569 chunk->MarkEmptyBlocks();
576 } 570 }
577 571
578 if (generator.GenerateCode()) { 572 if (generator.GenerateCode()) {
579 if (FLAG_trace_codegen) { 573 if (FLAG_trace_codegen) {
580 PrintF("Crankshaft Compiler - "); 574 PrintF("Crankshaft Compiler - ");
581 } 575 }
582 CodeGenerator::MakeCodePrologue(info()); 576 CodeGenerator::MakeCodePrologue(info);
583 Code::Flags flags = 577 Code::Flags flags =
584 Code::ComputeFlags(Code::OPTIMIZED_FUNCTION, NOT_IN_LOOP); 578 Code::ComputeFlags(Code::OPTIMIZED_FUNCTION, NOT_IN_LOOP);
585 Handle<Code> code = 579 Handle<Code> code =
586 CodeGenerator::MakeCodeEpilogue(&assembler, flags, info()); 580 CodeGenerator::MakeCodeEpilogue(&assembler, flags, info);
587 generator.FinishCode(code); 581 generator.FinishCode(code);
588 CodeGenerator::PrintCode(code, info()); 582 CodeGenerator::PrintCode(code, info);
589 return code; 583 return code;
590 } 584 }
591 return Handle<Code>::null(); 585 return Handle<Code>::null();
592 } 586 }
593 587
594 588
595 HBasicBlock* HGraph::CreateBasicBlock() { 589 HBasicBlock* HGraph::CreateBasicBlock() {
596 HBasicBlock* result = new HBasicBlock(this); 590 HBasicBlock* result = new HBasicBlock(this);
597 blocks_.Add(result); 591 blocks_.Add(result);
598 return result; 592 return result;
(...skipping 570 matching lines...) Expand 10 before | Expand all | Expand 10 after
1169 HGoto::cast(instr)->set_include_stack_check(false); 1163 HGoto::cast(instr)->set_include_stack_check(false);
1170 return; 1164 return;
1171 } 1165 }
1172 instr = instr->next(); 1166 instr = instr->next();
1173 } 1167 }
1174 } 1168 }
1175 1169
1176 1170
1177 class HGlobalValueNumberer BASE_EMBEDDED { 1171 class HGlobalValueNumberer BASE_EMBEDDED {
1178 public: 1172 public:
1179 explicit HGlobalValueNumberer(HGraph* graph) 1173 explicit HGlobalValueNumberer(HGraph* graph, CompilationInfo* info)
1180 : graph_(graph), 1174 : graph_(graph),
1175 info_(info),
1181 block_side_effects_(graph_->blocks()->length()), 1176 block_side_effects_(graph_->blocks()->length()),
1182 loop_side_effects_(graph_->blocks()->length()) { 1177 loop_side_effects_(graph_->blocks()->length()) {
1183 ASSERT(Heap::allow_allocation(false)); 1178 ASSERT(Heap::allow_allocation(false));
1184 block_side_effects_.AddBlock(0, graph_->blocks()->length()); 1179 block_side_effects_.AddBlock(0, graph_->blocks()->length());
1185 loop_side_effects_.AddBlock(0, graph_->blocks()->length()); 1180 loop_side_effects_.AddBlock(0, graph_->blocks()->length());
1186 } 1181 }
1187 ~HGlobalValueNumberer() { 1182 ~HGlobalValueNumberer() {
1188 ASSERT(!Heap::allow_allocation(true)); 1183 ASSERT(!Heap::allow_allocation(true));
1189 } 1184 }
1190 1185
1191 void Analyze(); 1186 void Analyze();
1192 1187
1193 private: 1188 private:
1194 void AnalyzeBlock(HBasicBlock* block, HValueMap* map); 1189 void AnalyzeBlock(HBasicBlock* block, HValueMap* map);
1195 void ComputeBlockSideEffects(); 1190 void ComputeBlockSideEffects();
1196 void LoopInvariantCodeMotion(); 1191 void LoopInvariantCodeMotion();
1197 void ProcessLoopBlock(HBasicBlock* block, 1192 void ProcessLoopBlock(HBasicBlock* block,
1198 HBasicBlock* before_loop, 1193 HBasicBlock* before_loop,
1199 int loop_kills); 1194 int loop_kills);
1195 bool AllowCodeMotion();
1200 bool ShouldMove(HInstruction* instr, HBasicBlock* loop_header); 1196 bool ShouldMove(HInstruction* instr, HBasicBlock* loop_header);
1201 1197
1198 HGraph* graph() { return graph_; }
1199 CompilationInfo* info() { return info_; }
1200
1202 HGraph* graph_; 1201 HGraph* graph_;
1202 CompilationInfo* info_;
1203 1203
1204 // A map of block IDs to their side effects. 1204 // A map of block IDs to their side effects.
1205 ZoneList<int> block_side_effects_; 1205 ZoneList<int> block_side_effects_;
1206 1206
1207 // A map of loop header block IDs to their loop's side effects. 1207 // A map of loop header block IDs to their loop's side effects.
1208 ZoneList<int> loop_side_effects_; 1208 ZoneList<int> loop_side_effects_;
1209 }; 1209 };
1210 1210
1211 1211
1212 void HGlobalValueNumberer::Analyze() { 1212 void HGlobalValueNumberer::Analyze() {
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
1293 // Move the instruction out of the loop. 1293 // Move the instruction out of the loop.
1294 instr->Unlink(); 1294 instr->Unlink();
1295 instr->InsertBefore(pre_header->end()); 1295 instr->InsertBefore(pre_header->end());
1296 } 1296 }
1297 } 1297 }
1298 instr = next; 1298 instr = next;
1299 } 1299 }
1300 } 1300 }
1301 1301
1302 1302
1303 bool HGlobalValueNumberer::AllowCodeMotion() {
1304 return info()->shared_info()->opt_count() + 1 < Compiler::kDefaultMaxOptCount;
1305 }
1306
1307
1303 bool HGlobalValueNumberer::ShouldMove(HInstruction* instr, 1308 bool HGlobalValueNumberer::ShouldMove(HInstruction* instr,
1304 HBasicBlock* loop_header) { 1309 HBasicBlock* loop_header) {
1305 // If we've disabled code motion, don't move any instructions. 1310 // If we've disabled code motion, don't move any instructions.
1306 if (!graph_->AllowCodeMotion()) return false; 1311 if (!AllowCodeMotion()) return false;
1307 1312
1308 // If --aggressive-loop-invariant-motion, move everything except change 1313 // If --aggressive-loop-invariant-motion, move everything except change
1309 // instructions. 1314 // instructions.
1310 if (FLAG_aggressive_loop_invariant_motion && !instr->IsChange()) { 1315 if (FLAG_aggressive_loop_invariant_motion && !instr->IsChange()) {
1311 return true; 1316 return true;
1312 } 1317 }
1313 1318
1314 // Otherwise only move instructions that postdominate the loop header 1319 // Otherwise only move instructions that postdominate the loop header
1315 // (i.e. are always executed inside the loop). This is to avoid 1320 // (i.e. are always executed inside the loop). This is to avoid
1316 // unnecessary deoptimizations assuming the loop is executed at least 1321 // unnecessary deoptimizations assuming the loop is executed at least
(...skipping 524 matching lines...) Expand 10 before | Expand all | Expand 10 after
1841 ASSERT(visited.IsEmpty()); 1846 ASSERT(visited.IsEmpty());
1842 PropagateMinusZeroChecks(change->value(), &visited); 1847 PropagateMinusZeroChecks(change->value(), &visited);
1843 visited.Clear(); 1848 visited.Clear();
1844 } 1849 }
1845 } 1850 }
1846 } 1851 }
1847 } 1852 }
1848 } 1853 }
1849 1854
1850 1855
1856 // Implementation of utility class to encapsulate the translation state for
1857 // a (possibly inlined) function.
1858 FunctionState::FunctionState(HGraphBuilder* owner,
1859 CompilationInfo* info,
1860 TypeFeedbackOracle* oracle)
1861 : owner_(owner),
1862 compilation_info_(info),
1863 oracle_(oracle),
1864 call_context_(NULL),
1865 function_return_(NULL),
1866 test_context_(NULL),
1867 outer_(owner->function_state()) {
1868 if (outer_ != NULL) {
1869 // State for an inline function.
1870 if (owner->ast_context()->IsTest()) {
1871 HBasicBlock* if_true = owner->graph()->CreateBasicBlock();
1872 HBasicBlock* if_false = owner->graph()->CreateBasicBlock();
1873 if_true->MarkAsInlineReturnTarget();
1874 if_false->MarkAsInlineReturnTarget();
1875 // The AstContext constructor pushed on the context stack. This newed
1876 // instance is the reason that AstContext can't be BASE_EMBEDDED.
1877 test_context_ = new TestContext(owner, if_true, if_false);
1878 } else {
1879 function_return_ = owner->graph()->CreateBasicBlock();
1880 function_return()->MarkAsInlineReturnTarget();
1881 }
1882 // Set this after possibly allocating a new TestContext above.
1883 call_context_ = owner->ast_context();
1884 }
1885
1886 // Push on the state stack.
1887 owner->set_function_state(this);
1888 }
1889
1890
1891 FunctionState::~FunctionState() {
1892 delete test_context_;
1893 owner_->set_function_state(outer_);
1894 }
1895
1896
1851 // Implementation of utility classes to represent an expression's context in 1897 // Implementation of utility classes to represent an expression's context in
1852 // the AST. 1898 // the AST.
1853 AstContext::AstContext(HGraphBuilder* owner, Expression::Context kind) 1899 AstContext::AstContext(HGraphBuilder* owner, Expression::Context kind)
1854 : owner_(owner), kind_(kind), outer_(owner->ast_context()) { 1900 : owner_(owner), kind_(kind), outer_(owner->ast_context()) {
1855 owner->set_ast_context(this); // Push. 1901 owner->set_ast_context(this); // Push.
1856 #ifdef DEBUG 1902 #ifdef DEBUG
1857 original_length_ = owner->environment()->length(); 1903 original_length_ = owner->environment()->length();
1858 #endif 1904 #endif
1859 } 1905 }
1860 1906
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after
2011 2057
2012 private: 2058 private:
2013 HGraphBuilder* builder_; 2059 HGraphBuilder* builder_;
2014 HSubgraph* old_subgraph_; 2060 HSubgraph* old_subgraph_;
2015 HSubgraph* subgraph_; 2061 HSubgraph* subgraph_;
2016 }; 2062 };
2017 2063
2018 2064
2019 void HGraphBuilder::Bailout(const char* reason) { 2065 void HGraphBuilder::Bailout(const char* reason) {
2020 if (FLAG_trace_bailout) { 2066 if (FLAG_trace_bailout) {
2021 SmartPointer<char> debug_name = graph()->debug_name()->ToCString(); 2067 SmartPointer<char> name(info()->shared_info()->DebugName()->ToCString());
2022 PrintF("Bailout in HGraphBuilder: @\"%s\": %s\n", *debug_name, reason); 2068 PrintF("Bailout in HGraphBuilder: @\"%s\": %s\n", *name, reason);
2023 } 2069 }
2024 SetStackOverflow(); 2070 SetStackOverflow();
2025 } 2071 }
2026 2072
2027 2073
2028 void HGraphBuilder::VisitForEffect(Expression* expr) { 2074 void HGraphBuilder::VisitForEffect(Expression* expr) {
2029 EffectContext for_effect(this); 2075 EffectContext for_effect(this);
2030 Visit(expr); 2076 Visit(expr);
2031 } 2077 }
2032 2078
(...skipping 26 matching lines...) Expand all
2059 } 2105 }
2060 2106
2061 2107
2062 void HGraphBuilder::VisitExpressions(ZoneList<Expression*>* exprs) { 2108 void HGraphBuilder::VisitExpressions(ZoneList<Expression*>* exprs) {
2063 for (int i = 0; i < exprs->length(); ++i) { 2109 for (int i = 0; i < exprs->length(); ++i) {
2064 VISIT_FOR_VALUE(exprs->at(i)); 2110 VISIT_FOR_VALUE(exprs->at(i));
2065 } 2111 }
2066 } 2112 }
2067 2113
2068 2114
2069 HGraph* HGraphBuilder::CreateGraph(CompilationInfo* info) { 2115 HGraph* HGraphBuilder::CreateGraph() {
2070 ASSERT(subgraph() == NULL); 2116 ASSERT(subgraph() == NULL);
2071 graph_ = new HGraph(info); 2117 graph_ = new HGraph(info());
2072 2118
2073 { 2119 {
2074 HPhase phase("Block building"); 2120 HPhase phase("Block building");
2075 graph()->Initialize(CreateBasicBlock(graph()->start_environment())); 2121 graph()->Initialize(CreateBasicBlock(graph()->start_environment()));
2076 current_subgraph_ = graph(); 2122 current_subgraph_ = graph();
2077 2123
2078 Scope* scope = info->scope(); 2124 Scope* scope = info()->scope();
2079 if (scope->HasIllegalRedeclaration()) { 2125 if (scope->HasIllegalRedeclaration()) {
2080 Bailout("function with illegal redeclaration"); 2126 Bailout("function with illegal redeclaration");
2081 return NULL; 2127 return NULL;
2082 } 2128 }
2083 SetupScope(scope); 2129 SetupScope(scope);
2084 VisitDeclarations(scope->declarations()); 2130 VisitDeclarations(scope->declarations());
2085 AddInstruction(new HStackCheck()); 2131 AddInstruction(new HStackCheck());
2086 2132
2087 // Add an edge to the body entry. This is warty: the graph's start 2133 // Add an edge to the body entry. This is warty: the graph's start
2088 // environment will be used by the Lithium translation as the initial 2134 // environment will be used by the Lithium translation as the initial
2089 // environment on graph entry, but it has now been mutated by the 2135 // environment on graph entry, but it has now been mutated by the
2090 // Hydrogen translation of the instructions in the start block. This 2136 // Hydrogen translation of the instructions in the start block. This
2091 // environment uses values which have not been defined yet. These 2137 // environment uses values which have not been defined yet. These
2092 // Hydrogen instructions will then be replayed by the Lithium 2138 // Hydrogen instructions will then be replayed by the Lithium
2093 // translation, so they cannot have an environment effect. The edge to 2139 // translation, so they cannot have an environment effect. The edge to
2094 // the body's entry block (along with some special logic for the start 2140 // the body's entry block (along with some special logic for the start
2095 // block in HInstruction::InsertAfter) seals the start block from 2141 // block in HInstruction::InsertAfter) seals the start block from
2096 // getting unwanted instructions inserted. 2142 // getting unwanted instructions inserted.
2097 // 2143 //
2098 // TODO(kmillikin): Fix this. Stop mutating the initial environment. 2144 // TODO(kmillikin): Fix this. Stop mutating the initial environment.
2099 // Make the Hydrogen instructions in the initial block into Hydrogen 2145 // Make the Hydrogen instructions in the initial block into Hydrogen
2100 // values (but not instructions), present in the initial environment and 2146 // values (but not instructions), present in the initial environment and
2101 // not replayed by the Lithium translation. 2147 // not replayed by the Lithium translation.
2102 HEnvironment* initial_env = environment()->CopyWithoutHistory(); 2148 HEnvironment* initial_env = environment()->CopyWithoutHistory();
2103 HBasicBlock* body_entry = CreateBasicBlock(initial_env); 2149 HBasicBlock* body_entry = CreateBasicBlock(initial_env);
2104 current_block()->Goto(body_entry); 2150 current_block()->Goto(body_entry);
2105 body_entry->SetJoinId(info->function()->id()); 2151 body_entry->SetJoinId(info()->function()->id());
2106 set_current_block(body_entry); 2152 set_current_block(body_entry);
2107 VisitStatements(info->function()->body()); 2153 VisitStatements(info()->function()->body());
2108 if (HasStackOverflow()) return NULL; 2154 if (HasStackOverflow()) return NULL;
2109 2155
2110 if (current_block() != NULL) { 2156 if (current_block() != NULL) {
2111 HReturn* instr = new HReturn(graph()->GetConstantUndefined()); 2157 HReturn* instr = new HReturn(graph()->GetConstantUndefined());
2112 current_block()->FinishExit(instr); 2158 current_block()->FinishExit(instr);
2113 set_current_block(NULL); 2159 set_current_block(NULL);
2114 } 2160 }
2115 } 2161 }
2116 2162
2117 graph()->OrderBlocks(); 2163 graph()->OrderBlocks();
(...skipping 17 matching lines...) Expand all
2135 graph()->InsertRepresentationChanges(); 2181 graph()->InsertRepresentationChanges();
2136 graph()->ComputeMinusZeroChecks(); 2182 graph()->ComputeMinusZeroChecks();
2137 2183
2138 // Eliminate redundant stack checks on backwards branches. 2184 // Eliminate redundant stack checks on backwards branches.
2139 HStackCheckEliminator sce(graph()); 2185 HStackCheckEliminator sce(graph());
2140 sce.Process(); 2186 sce.Process();
2141 2187
2142 // Perform common subexpression elimination and loop-invariant code motion. 2188 // Perform common subexpression elimination and loop-invariant code motion.
2143 if (FLAG_use_gvn) { 2189 if (FLAG_use_gvn) {
2144 HPhase phase("Global value numbering", graph()); 2190 HPhase phase("Global value numbering", graph());
2145 HGlobalValueNumberer gvn(graph()); 2191 HGlobalValueNumberer gvn(graph(), info());
2146 gvn.Analyze(); 2192 gvn.Analyze();
2147 } 2193 }
2148 2194
2149 return graph(); 2195 return graph();
2150 } 2196 }
2151 2197
2152 2198
2153 void HGraphBuilder::AddToSubgraph(HSubgraph* graph, Statement* stmt) { 2199 void HGraphBuilder::AddToSubgraph(HSubgraph* graph, Statement* stmt) {
2154 SubgraphScope scope(this, graph); 2200 SubgraphScope scope(this, graph);
2155 Visit(stmt); 2201 Visit(stmt);
(...skipping 260 matching lines...) Expand 10 before | Expand all | Expand 10 after
2416 HValue* return_value = NULL; 2462 HValue* return_value = NULL;
2417 if (context->IsEffect()) { 2463 if (context->IsEffect()) {
2418 VISIT_FOR_EFFECT(stmt->expression()); 2464 VISIT_FOR_EFFECT(stmt->expression());
2419 return_value = graph()->GetConstantUndefined(); 2465 return_value = graph()->GetConstantUndefined();
2420 } else { 2466 } else {
2421 ASSERT(context->IsValue()); 2467 ASSERT(context->IsValue());
2422 VISIT_FOR_VALUE(stmt->expression()); 2468 VISIT_FOR_VALUE(stmt->expression());
2423 return_value = environment()->Pop(); 2469 return_value = environment()->Pop();
2424 } 2470 }
2425 current_block()->AddLeaveInlined(return_value, 2471 current_block()->AddLeaveInlined(return_value,
2426 function_return_); 2472 function_return());
2427 set_current_block(NULL); 2473 set_current_block(NULL);
2428 } 2474 }
2429 } 2475 }
2430 } 2476 }
2431 2477
2432 2478
2433 void HGraphBuilder::VisitWithEnterStatement(WithEnterStatement* stmt) { 2479 void HGraphBuilder::VisitWithEnterStatement(WithEnterStatement* stmt) {
2434 BAILOUT("WithEnterStatement"); 2480 BAILOUT("WithEnterStatement");
2435 } 2481 }
2436 2482
(...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after
2600 last_false_block->Finish(new HGoto(single_exit_block)); 2646 last_false_block->Finish(new HGoto(single_exit_block));
2601 } 2647 }
2602 2648
2603 if (single_exit_block->HasPredecessor()) { 2649 if (single_exit_block->HasPredecessor()) {
2604 set_current_block(single_exit_block); 2650 set_current_block(single_exit_block);
2605 } else { 2651 } else {
2606 set_current_block(NULL); 2652 set_current_block(NULL);
2607 } 2653 }
2608 } 2654 }
2609 2655
2610 bool HGraph::HasOsrEntryAt(IterationStatement* statement) { 2656 bool HGraphBuilder::HasOsrEntryAt(IterationStatement* statement) {
2611 return statement->OsrEntryId() == info()->osr_ast_id(); 2657 return statement->OsrEntryId() == info()->osr_ast_id();
2612 } 2658 }
2613 2659
2614 2660
2615 void HGraphBuilder::PreProcessOsrEntry(IterationStatement* statement) { 2661 void HGraphBuilder::PreProcessOsrEntry(IterationStatement* statement) {
2616 if (!graph()->HasOsrEntryAt(statement)) return; 2662 if (!HasOsrEntryAt(statement)) return;
2617 2663
2618 HBasicBlock* non_osr_entry = graph()->CreateBasicBlock(); 2664 HBasicBlock* non_osr_entry = graph()->CreateBasicBlock();
2619 HBasicBlock* osr_entry = graph()->CreateBasicBlock(); 2665 HBasicBlock* osr_entry = graph()->CreateBasicBlock();
2620 HValue* true_value = graph()->GetConstantTrue(); 2666 HValue* true_value = graph()->GetConstantTrue();
2621 HTest* test = new HTest(true_value, non_osr_entry, osr_entry); 2667 HTest* test = new HTest(true_value, non_osr_entry, osr_entry);
2622 current_block()->Finish(test); 2668 current_block()->Finish(test);
2623 2669
2624 HBasicBlock* loop_predecessor = graph()->CreateBasicBlock(); 2670 HBasicBlock* loop_predecessor = graph()->CreateBasicBlock();
2625 non_osr_entry->Goto(loop_predecessor); 2671 non_osr_entry->Goto(loop_predecessor);
2626 2672
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after
2773 } 2819 }
2774 2820
2775 2821
2776 void HGraphBuilder::VisitDebuggerStatement(DebuggerStatement* stmt) { 2822 void HGraphBuilder::VisitDebuggerStatement(DebuggerStatement* stmt) {
2777 BAILOUT("DebuggerStatement"); 2823 BAILOUT("DebuggerStatement");
2778 } 2824 }
2779 2825
2780 2826
2781 void HGraphBuilder::VisitFunctionLiteral(FunctionLiteral* expr) { 2827 void HGraphBuilder::VisitFunctionLiteral(FunctionLiteral* expr) {
2782 Handle<SharedFunctionInfo> shared_info = 2828 Handle<SharedFunctionInfo> shared_info =
2783 Compiler::BuildFunctionInfo(expr, graph_->info()->script()); 2829 Compiler::BuildFunctionInfo(expr, info()->script());
2784 CHECK_BAILOUT; 2830 CHECK_BAILOUT;
2785 HFunctionLiteral* instr = 2831 HFunctionLiteral* instr =
2786 new HFunctionLiteral(shared_info, expr->pretenure()); 2832 new HFunctionLiteral(shared_info, expr->pretenure());
2787 ast_context()->ReturnInstruction(instr, expr->id()); 2833 ast_context()->ReturnInstruction(instr, expr->id());
2788 } 2834 }
2789 2835
2790 2836
2791 void HGraphBuilder::VisitSharedFunctionInfoLiteral( 2837 void HGraphBuilder::VisitSharedFunctionInfoLiteral(
2792 SharedFunctionInfoLiteral* expr) { 2838 SharedFunctionInfoLiteral* expr) {
2793 BAILOUT("SharedFunctionInfoLiteral"); 2839 BAILOUT("SharedFunctionInfoLiteral");
(...skipping 21 matching lines...) Expand all
2815 ast_context()->ReturnValue(Pop()); 2861 ast_context()->ReturnValue(Pop());
2816 } 2862 }
2817 2863
2818 2864
2819 void HGraphBuilder::LookupGlobalPropertyCell(Variable* var, 2865 void HGraphBuilder::LookupGlobalPropertyCell(Variable* var,
2820 LookupResult* lookup, 2866 LookupResult* lookup,
2821 bool is_store) { 2867 bool is_store) {
2822 if (var->is_this()) { 2868 if (var->is_this()) {
2823 BAILOUT("global this reference"); 2869 BAILOUT("global this reference");
2824 } 2870 }
2825 if (!graph()->info()->has_global_object()) { 2871 if (!info()->has_global_object()) {
2826 BAILOUT("no global object to optimize VariableProxy"); 2872 BAILOUT("no global object to optimize VariableProxy");
2827 } 2873 }
2828 Handle<GlobalObject> global(graph()->info()->global_object()); 2874 Handle<GlobalObject> global(info()->global_object());
2829 global->Lookup(*var->name(), lookup); 2875 global->Lookup(*var->name(), lookup);
2830 if (!lookup->IsProperty()) { 2876 if (!lookup->IsProperty()) {
2831 BAILOUT("global variable cell not yet introduced"); 2877 BAILOUT("global variable cell not yet introduced");
2832 } 2878 }
2833 if (lookup->type() != NORMAL) { 2879 if (lookup->type() != NORMAL) {
2834 BAILOUT("global variable has accessors"); 2880 BAILOUT("global variable has accessors");
2835 } 2881 }
2836 if (is_store && lookup->IsReadOnly()) { 2882 if (is_store && lookup->IsReadOnly()) {
2837 BAILOUT("read-only global variable"); 2883 BAILOUT("read-only global variable");
2838 } 2884 }
2839 if (lookup->holder() != *global) { 2885 if (lookup->holder() != *global) {
2840 BAILOUT("global property on prototype of global object"); 2886 BAILOUT("global property on prototype of global object");
2841 } 2887 }
2842 } 2888 }
2843 2889
2844 2890
2845 HValue* HGraphBuilder::BuildContextChainWalk(Variable* var) { 2891 HValue* HGraphBuilder::BuildContextChainWalk(Variable* var) {
2846 ASSERT(var->IsContextSlot()); 2892 ASSERT(var->IsContextSlot());
2847 HInstruction* context = new HContext; 2893 HInstruction* context = new HContext;
2848 AddInstruction(context); 2894 AddInstruction(context);
2849 int length = graph()->info()->scope()->ContextChainLength(var->scope()); 2895 int length = info()->scope()->ContextChainLength(var->scope());
2850 while (length-- > 0) { 2896 while (length-- > 0) {
2851 context = new HOuterContext(context); 2897 context = new HOuterContext(context);
2852 AddInstruction(context); 2898 AddInstruction(context);
2853 } 2899 }
2854 return context; 2900 return context;
2855 } 2901 }
2856 2902
2857 2903
2858 void HGraphBuilder::VisitVariableProxy(VariableProxy* expr) { 2904 void HGraphBuilder::VisitVariableProxy(VariableProxy* expr) {
2859 Variable* variable = expr->AsVariable(); 2905 Variable* variable = expr->AsVariable();
(...skipping 10 matching lines...) Expand all
2870 } 2916 }
2871 HValue* context = BuildContextChainWalk(variable); 2917 HValue* context = BuildContextChainWalk(variable);
2872 int index = variable->AsSlot()->index(); 2918 int index = variable->AsSlot()->index();
2873 HLoadContextSlot* instr = new HLoadContextSlot(context, index); 2919 HLoadContextSlot* instr = new HLoadContextSlot(context, index);
2874 ast_context()->ReturnInstruction(instr, expr->id()); 2920 ast_context()->ReturnInstruction(instr, expr->id());
2875 } else if (variable->is_global()) { 2921 } else if (variable->is_global()) {
2876 LookupResult lookup; 2922 LookupResult lookup;
2877 LookupGlobalPropertyCell(variable, &lookup, false); 2923 LookupGlobalPropertyCell(variable, &lookup, false);
2878 CHECK_BAILOUT; 2924 CHECK_BAILOUT;
2879 2925
2880 Handle<GlobalObject> global(graph()->info()->global_object()); 2926 Handle<GlobalObject> global(info()->global_object());
2881 // TODO(3039103): Handle global property load through an IC call when access 2927 // TODO(3039103): Handle global property load through an IC call when access
2882 // checks are enabled. 2928 // checks are enabled.
2883 if (global->IsAccessCheckNeeded()) { 2929 if (global->IsAccessCheckNeeded()) {
2884 BAILOUT("global object requires access check"); 2930 BAILOUT("global object requires access check");
2885 } 2931 }
2886 Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(&lookup)); 2932 Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(&lookup));
2887 bool check_hole = !lookup.IsDontDelete() || lookup.IsReadOnly(); 2933 bool check_hole = !lookup.IsDontDelete() || lookup.IsReadOnly();
2888 HLoadGlobal* instr = new HLoadGlobal(cell, check_hole); 2934 HLoadGlobal* instr = new HLoadGlobal(cell, check_hole);
2889 ast_context()->ReturnInstruction(instr, expr->id()); 2935 ast_context()->ReturnInstruction(instr, expr->id());
2890 } else { 2936 } else {
(...skipping 249 matching lines...) Expand 10 before | Expand all | Expand 10 after
3140 true) // Needs smi and map check. 3186 true) // Needs smi and map check.
3141 : BuildStoreNamedGeneric(object, name, value); 3187 : BuildStoreNamedGeneric(object, name, value);
3142 } 3188 }
3143 3189
3144 3190
3145 void HGraphBuilder::HandlePolymorphicStoreNamedField(Assignment* expr, 3191 void HGraphBuilder::HandlePolymorphicStoreNamedField(Assignment* expr,
3146 HValue* object, 3192 HValue* object,
3147 HValue* value, 3193 HValue* value,
3148 ZoneMapList* types, 3194 ZoneMapList* types,
3149 Handle<String> name) { 3195 Handle<String> name) {
3196 // TODO(ager): We should recognize when the prototype chains for different
3197 // maps are identical. In that case we can avoid repeatedly generating the
3198 // same prototype map checks.
3150 int count = 0; 3199 int count = 0;
3151 HBasicBlock* join = NULL; 3200 HBasicBlock* join = NULL;
3152 for (int i = 0; i < types->length() && count < kMaxStorePolymorphism; ++i) { 3201 for (int i = 0; i < types->length() && count < kMaxStorePolymorphism; ++i) {
3153 Handle<Map> map = types->at(i); 3202 Handle<Map> map = types->at(i);
3154 LookupResult lookup; 3203 LookupResult lookup;
3155 if (ComputeStoredField(map, name, &lookup)) { 3204 if (ComputeStoredField(map, name, &lookup)) {
3156 ++count; 3205 if (count == 0) {
3157 if (join == NULL) {
3158 AddInstruction(new HCheckNonSmi(object)); // Only needed once. 3206 AddInstruction(new HCheckNonSmi(object)); // Only needed once.
3159 join = graph()->CreateBasicBlock(); 3207 join = graph()->CreateBasicBlock();
3160 } 3208 }
3209 ++count;
3161 HBasicBlock* if_true = graph()->CreateBasicBlock(); 3210 HBasicBlock* if_true = graph()->CreateBasicBlock();
3162 HBasicBlock* if_false = graph()->CreateBasicBlock(); 3211 HBasicBlock* if_false = graph()->CreateBasicBlock();
3163 HCompareMap* compare = new HCompareMap(object, map, if_true, if_false); 3212 HCompareMap* compare = new HCompareMap(object, map, if_true, if_false);
3164 current_block()->Finish(compare); 3213 current_block()->Finish(compare);
3165 3214
3166 set_current_block(if_true); 3215 set_current_block(if_true);
3167 HInstruction* instr = 3216 HInstruction* instr =
3168 BuildStoreNamedField(object, name, value, map, &lookup, false); 3217 BuildStoreNamedField(object, name, value, map, &lookup, false);
3169 instr->set_position(expr->position()); 3218 instr->set_position(expr->position());
3170 // Goto will add the HSimulate for the store. 3219 // Goto will add the HSimulate for the store.
3171 AddInstruction(instr); 3220 AddInstruction(instr);
3172 if (!ast_context()->IsEffect()) Push(value); 3221 if (!ast_context()->IsEffect()) Push(value);
3173 current_block()->Goto(join); 3222 current_block()->Goto(join);
3174 3223
3175 set_current_block(if_false); 3224 set_current_block(if_false);
3176 } 3225 }
3177 } 3226 }
3178 3227
3179 // Finish up. We need a generic IC if there were types we couldn't 3228 // Finish up. Unconditionally deoptimize if we've handled all the maps we
3180 // resolve statically or if we want to handle maps we've never seen. 3229 // know about and do not want to handle ones we've never seen. Otherwise
3181 if (count < types->length() || !FLAG_deoptimize_uncommon_cases) { 3230 // use a generic IC.
3231 if (count == types->length() && FLAG_deoptimize_uncommon_cases) {
fschneider 2011/03/07 11:29:47 Remove extra space.
3232 current_block()->FinishExit(new HDeoptimize);
3233 } else {
3182 HInstruction* instr = BuildStoreNamedGeneric(object, name, value); 3234 HInstruction* instr = BuildStoreNamedGeneric(object, name, value);
3183 instr->set_position(expr->position()); 3235 instr->set_position(expr->position());
3184 AddInstruction(instr); 3236 AddInstruction(instr);
3185 3237
3186 if (join == NULL) { 3238 if (join != NULL) {
3239 if (!ast_context()->IsEffect()) Push(value);
3240 current_block()->Goto(join);
3241 } else {
3187 // The HSimulate for the store should not see the stored value in 3242 // The HSimulate for the store should not see the stored value in
3188 // effect contexts (it is not materialized at expr->id() in the 3243 // effect contexts (it is not materialized at expr->id() in the
3189 // unoptimized code). 3244 // unoptimized code).
3190 if (instr->HasSideEffects()) { 3245 if (instr->HasSideEffects()) {
fschneider 2011/03/07 11:29:47 HasSideEffects() is always true for HStoreNamedGen
Kevin Millikin (Chromium) 2011/03/07 11:51:52 But this code shouldn't rely on assuming the type
3191 if (ast_context()->IsEffect()) { 3246 if (ast_context()->IsEffect()) {
3192 AddSimulate(expr->id()); 3247 AddSimulate(expr->id());
3193 } else { 3248 } else {
3194 Push(value); 3249 Push(value);
3195 AddSimulate(expr->id()); 3250 AddSimulate(expr->id());
3196 Drop(1); 3251 Drop(1);
3197 } 3252 }
3198 } 3253 }
3199 ast_context()->ReturnValue(value); 3254 ast_context()->ReturnValue(value);
3200 } else { 3255 return;
3201 if (!ast_context()->IsEffect()) Push(value);
3202 current_block()->Goto(join);
3203 join->SetJoinId(expr->id());
3204 set_current_block(join);
3205 if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop());
3206 }
3207
3208 } else {
3209 current_block()->FinishExit(new HDeoptimize);
3210 set_current_block(join);
3211 if (join != NULL) {
3212 join->SetJoinId(expr->id());
3213 if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop());
3214 } 3256 }
3215 } 3257 }
3258
3259 ASSERT(join != NULL);
3260 join->SetJoinId(expr->id());
3261 set_current_block(join);
3262 if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop());
3216 } 3263 }
3217 3264
3218 3265
3219 void HGraphBuilder::HandlePropertyAssignment(Assignment* expr) { 3266 void HGraphBuilder::HandlePropertyAssignment(Assignment* expr) {
3220 Property* prop = expr->target()->AsProperty(); 3267 Property* prop = expr->target()->AsProperty();
3221 ASSERT(prop != NULL); 3268 ASSERT(prop != NULL);
3222 expr->RecordTypeFeedback(oracle()); 3269 expr->RecordTypeFeedback(oracle());
3223 VISIT_FOR_VALUE(prop->obj()); 3270 VISIT_FOR_VALUE(prop->obj());
3224 3271
3225 HValue* value = NULL; 3272 HValue* value = NULL;
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
3286 // owning expression instead of position and ast_id separately. 3333 // owning expression instead of position and ast_id separately.
3287 void HGraphBuilder::HandleGlobalVariableAssignment(Variable* var, 3334 void HGraphBuilder::HandleGlobalVariableAssignment(Variable* var,
3288 HValue* value, 3335 HValue* value,
3289 int position, 3336 int position,
3290 int ast_id) { 3337 int ast_id) {
3291 LookupResult lookup; 3338 LookupResult lookup;
3292 LookupGlobalPropertyCell(var, &lookup, true); 3339 LookupGlobalPropertyCell(var, &lookup, true);
3293 CHECK_BAILOUT; 3340 CHECK_BAILOUT;
3294 3341
3295 bool check_hole = !lookup.IsDontDelete() || lookup.IsReadOnly(); 3342 bool check_hole = !lookup.IsDontDelete() || lookup.IsReadOnly();
3296 Handle<GlobalObject> global(graph()->info()->global_object()); 3343 Handle<GlobalObject> global(info()->global_object());
3297 Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(&lookup)); 3344 Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(&lookup));
3298 HInstruction* instr = new HStoreGlobal(value, cell, check_hole); 3345 HInstruction* instr = new HStoreGlobal(value, cell, check_hole);
3299 instr->set_position(position); 3346 instr->set_position(position);
3300 AddInstruction(instr); 3347 AddInstruction(instr);
3301 if (instr->HasSideEffects()) AddSimulate(ast_id); 3348 if (instr->HasSideEffects()) AddSimulate(ast_id);
3302 } 3349 }
3303 3350
3304 3351
3305 void HGraphBuilder::HandleCompoundAssignment(Assignment* expr) { 3352 void HGraphBuilder::HandleCompoundAssignment(Assignment* expr) {
3306 Expression* target = expr->target(); 3353 Expression* target = expr->target();
(...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after
3484 AddSimulate(expr->id()); 3531 AddSimulate(expr->id());
3485 current_block()->FinishExit(new HAbnormalExit); 3532 current_block()->FinishExit(new HAbnormalExit);
3486 set_current_block(NULL); 3533 set_current_block(NULL);
3487 } 3534 }
3488 3535
3489 3536
3490 void HGraphBuilder::HandlePolymorphicLoadNamedField(Property* expr, 3537 void HGraphBuilder::HandlePolymorphicLoadNamedField(Property* expr,
3491 HValue* object, 3538 HValue* object,
3492 ZoneMapList* types, 3539 ZoneMapList* types,
3493 Handle<String> name) { 3540 Handle<String> name) {
3494 int number_of_types = Min(types->length(), kMaxLoadPolymorphism); 3541 // TODO(ager): We should recognize when the prototype chains for different
3495 ZoneMapList maps(number_of_types); 3542 // maps are identical. In that case we can avoid repeatedly generating the
3496 ZoneList<HSubgraph*> subgraphs(number_of_types); 3543 // same prototype map checks.
3497 bool needs_generic = (types->length() > kMaxLoadPolymorphism); 3544 int count = 0;
3498 3545 HBasicBlock* join = NULL;
3499 // Build subgraphs for each of the specific maps. 3546 for (int i = 0; i < types->length() && count < kMaxLoadPolymorphism; ++i) {
3500 //
3501 // TODO(ager): We should recognize when the prototype chains for
3502 // different maps are identical. In that case we can avoid
3503 // repeatedly generating the same prototype map checks.
3504 for (int i = 0; i < number_of_types; ++i) {
3505 Handle<Map> map = types->at(i); 3547 Handle<Map> map = types->at(i);
3506 LookupResult lookup; 3548 LookupResult lookup;
3507 map->LookupInDescriptors(NULL, *name, &lookup); 3549 map->LookupInDescriptors(NULL, *name, &lookup);
3508 if (lookup.IsProperty() && lookup.type() == FIELD) { 3550 if (lookup.IsProperty() && lookup.type() == FIELD) {
3509 HSubgraph* subgraph = CreateBranchSubgraph(environment()); 3551 if (count == 0) {
3510 SubgraphScope scope(this, subgraph); 3552 AddInstruction(new HCheckNonSmi(object)); // Only needed once.
3553 join = graph()->CreateBasicBlock();
3554 }
3555 ++count;
3556 HBasicBlock* if_true = graph()->CreateBasicBlock();
3557 HBasicBlock* if_false = graph()->CreateBasicBlock();
3558 HCompareMap* compare = new HCompareMap(object, map, if_true, if_false);
3559 current_block()->Finish(compare);
3560
3561 set_current_block(if_true);
3511 HLoadNamedField* instr = 3562 HLoadNamedField* instr =
3512 BuildLoadNamedField(object, expr, map, &lookup, false); 3563 BuildLoadNamedField(object, expr, map, &lookup, false);
3513 instr->set_position(expr->position()); 3564 instr->set_position(expr->position());
3514 instr->ClearFlag(HValue::kUseGVN); // Don't do GVN on polymorphic loads. 3565 instr->ClearFlag(HValue::kUseGVN);
3515 PushAndAdd(instr); 3566 AddInstruction(instr);
3516 maps.Add(map); 3567 if (!ast_context()->IsEffect()) Push(instr);
3517 subgraphs.Add(subgraph); 3568 current_block()->Goto(join);
3569
3570 set_current_block(if_false);
3571 }
fschneider 2011/03/07 11:29:47 Remove extra space.
Kevin Millikin (Chromium) 2011/03/07 11:51:52 Thanks.
3572 }
3573
3574 // Finish up. Unconditionally deoptimize if we've handled all the maps we
3575 // know about and do not want to handle ones we've never seen. Otherwise
3576 // use a generic IC.
3577 if (count == types->length() && FLAG_deoptimize_uncommon_cases) {
3578 current_block()->FinishExit(new HDeoptimize);
3579 } else {
3580 HInstruction* instr = BuildLoadNamedGeneric(object, expr);
3581 instr->set_position(expr->position());
3582
3583 if (join != NULL) {
3584 AddInstruction(instr);
3585 if (!ast_context()->IsEffect()) Push(instr);
3586 current_block()->Goto(join);
3518 } else { 3587 } else {
3519 needs_generic = true; 3588 ast_context()->ReturnInstruction(instr, expr->id());
3589 return;
3520 } 3590 }
3521 } 3591 }
3522 3592
3523 // If none of the properties were named fields we generate a 3593 ASSERT(join != NULL);
3524 // generic load. 3594 join->SetJoinId(expr->id());
3525 if (maps.length() == 0) { 3595 set_current_block(join);
3526 HInstruction* instr = BuildLoadNamedGeneric(object, expr); 3596 if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop());
3527 instr->set_position(expr->position());
3528 ast_context()->ReturnInstruction(instr, expr->id());
3529 } else {
3530 // Build subgraph for generic load through IC.
3531 HSubgraph* default_graph = CreateBranchSubgraph(environment());
3532 { SubgraphScope scope(this, default_graph);
3533 if (!needs_generic && FLAG_deoptimize_uncommon_cases) {
3534 default_graph->exit_block()->FinishExit(new HDeoptimize());
3535 default_graph->set_exit_block(NULL);
3536 } else {
3537 HInstruction* instr = BuildLoadNamedGeneric(object, expr);
3538 instr->set_position(expr->position());
3539 PushAndAdd(instr);
3540 }
3541 }
3542
3543 HBasicBlock* new_exit_block =
3544 BuildTypeSwitch(object, &maps, &subgraphs, default_graph, expr->id());
3545 set_current_block(new_exit_block);
3546 // In an effect context, we did not materialized the value in the
3547 // predecessor environments so there's no need to handle it here.
3548 if (current_block() != NULL && !ast_context()->IsEffect()) {
3549 ast_context()->ReturnValue(Pop());
3550 }
3551 }
3552 } 3597 }
3553 3598
3554 3599
3555 HLoadNamedField* HGraphBuilder::BuildLoadNamedField(HValue* object, 3600 HLoadNamedField* HGraphBuilder::BuildLoadNamedField(HValue* object,
3556 Property* expr, 3601 Property* expr,
3557 Handle<Map> type, 3602 Handle<Map> type,
3558 LookupResult* lookup, 3603 LookupResult* lookup,
3559 bool smi_and_map_check) { 3604 bool smi_and_map_check) {
3560 if (smi_and_map_check) { 3605 if (smi_and_map_check) {
3561 AddInstruction(new HCheckNonSmi(object)); 3606 AddInstruction(new HCheckNonSmi(object));
(...skipping 347 matching lines...) Expand 10 before | Expand all | Expand 10 after
3909 set_current_block(new_exit_block); 3954 set_current_block(new_exit_block);
3910 // In an effect context, we did not materialized the value in the 3955 // In an effect context, we did not materialized the value in the
3911 // predecessor environments so there's no need to handle it here. 3956 // predecessor environments so there's no need to handle it here.
3912 if (new_exit_block != NULL && !ast_context()->IsEffect()) { 3957 if (new_exit_block != NULL && !ast_context()->IsEffect()) {
3913 ast_context()->ReturnValue(Pop()); 3958 ast_context()->ReturnValue(Pop());
3914 } 3959 }
3915 } 3960 }
3916 } 3961 }
3917 3962
3918 3963
3919 void HGraphBuilder::TraceInline(Handle<JSFunction> target, bool result) { 3964 void HGraphBuilder::TraceInline(Handle<JSFunction> target, const char* reason) {
3920 SmartPointer<char> callee = target->shared()->DebugName()->ToCString(); 3965 if (FLAG_trace_inlining) {
3921 SmartPointer<char> caller = 3966 SmartPointer<char> callee = target->shared()->DebugName()->ToCString();
3922 graph()->info()->function()->debug_name()->ToCString(); 3967 SmartPointer<char> caller =
3923 if (result) { 3968 info()->function()->debug_name()->ToCString();
3924 PrintF("Inlined %s called from %s.\n", *callee, *caller); 3969 if (reason == NULL) {
3925 } else { 3970 PrintF("Inlined %s called from %s.\n", *callee, *caller);
3926 PrintF("Do not inline %s called from %s.\n", *callee, *caller); 3971 } else {
3972 PrintF("Did not inline %s called from %s (%s).\n",
3973 *callee, *caller, reason);
3974 }
3927 } 3975 }
3928 } 3976 }
3929 3977
3930 3978
3931 bool HGraphBuilder::TryInline(Call* expr) { 3979 bool HGraphBuilder::TryInline(Call* expr) {
3932 if (!FLAG_use_inlining) return false; 3980 if (!FLAG_use_inlining) return false;
3933 3981
3934 // Precondition: call is monomorphic and we have found a target with the 3982 // Precondition: call is monomorphic and we have found a target with the
3935 // appropriate arity. 3983 // appropriate arity.
3936 Handle<JSFunction> target = expr->target(); 3984 Handle<JSFunction> target = expr->target();
3937 3985
3938 // Do a quick check on source code length to avoid parsing large 3986 // Do a quick check on source code length to avoid parsing large
3939 // inlining candidates. 3987 // inlining candidates.
3940 if (FLAG_limit_inlining && target->shared()->SourceSize() > kMaxSourceSize) { 3988 if (FLAG_limit_inlining && target->shared()->SourceSize() > kMaxSourceSize) {
3941 if (FLAG_trace_inlining) TraceInline(target, false); 3989 TraceInline(target, "target text too big");
3942 return false; 3990 return false;
3943 } 3991 }
3944 3992
3945 // Target must be inlineable. 3993 // Target must be inlineable.
3946 if (!target->IsInlineable()) return false; 3994 if (!target->IsInlineable()) {
3995 TraceInline(target, "target not inlineable");
3996 return false;
3997 }
3947 3998
3948 // No context change required. 3999 // No context change required.
3949 CompilationInfo* outer_info = graph()->info(); 4000 CompilationInfo* outer_info = info();
3950 if (target->context() != outer_info->closure()->context() || 4001 if (target->context() != outer_info->closure()->context() ||
3951 outer_info->scope()->contains_with() || 4002 outer_info->scope()->contains_with() ||
3952 outer_info->scope()->num_heap_slots() > 0) { 4003 outer_info->scope()->num_heap_slots() > 0) {
4004 TraceInline(target, "target requires context change");
3953 return false; 4005 return false;
3954 } 4006 }
3955 4007
3956 // Don't inline deeper than two calls. 4008 // Don't inline deeper than two calls.
3957 HEnvironment* env = environment(); 4009 HEnvironment* env = environment();
3958 if (env->outer() != NULL && env->outer()->outer() != NULL) return false; 4010 if (env->outer() != NULL && env->outer()->outer() != NULL) {
4011 TraceInline(target, "inline depth limit reached");
4012 return false;
4013 }
3959 4014
3960 // Don't inline recursive functions. 4015 // Don't inline recursive functions.
3961 if (target->shared() == outer_info->closure()->shared()) return false; 4016 if (target->shared() == outer_info->closure()->shared()) {
4017 TraceInline(target, "target is recursive");
4018 return false;
4019 }
3962 4020
3963 // We don't want to add more than a certain number of nodes from inlining. 4021 // We don't want to add more than a certain number of nodes from inlining.
3964 if (FLAG_limit_inlining && inlined_count_ > kMaxInlinedNodes) { 4022 if (FLAG_limit_inlining && inlined_count_ > kMaxInlinedNodes) {
3965 if (FLAG_trace_inlining) TraceInline(target, false); 4023 TraceInline(target, "cumulative AST node limit reached");
3966 return false; 4024 return false;
3967 } 4025 }
3968 4026
3969 int count_before = AstNode::Count(); 4027 int count_before = AstNode::Count();
3970 4028
3971 // Parse and allocate variables. 4029 // Parse and allocate variables.
3972 CompilationInfo inner_info(target); 4030 CompilationInfo target_info(target);
3973 if (!ParserApi::Parse(&inner_info) || 4031 if (!ParserApi::Parse(&target_info) ||
3974 !Scope::Analyze(&inner_info)) { 4032 !Scope::Analyze(&target_info)) {
3975 if (Top::has_pending_exception()) { 4033 if (Top::has_pending_exception()) {
4034 // Parse or scope error, never optimize this function.
3976 SetStackOverflow(); 4035 SetStackOverflow();
3977 // Stop trying to optimize and inline this function.
3978 target->shared()->set_optimization_disabled(true); 4036 target->shared()->set_optimization_disabled(true);
3979 } 4037 }
4038 TraceInline(target, "parse failure");
3980 return false; 4039 return false;
3981 } 4040 }
3982 if (inner_info.scope()->num_heap_slots() > 0) return false; 4041
3983 FunctionLiteral* function = inner_info.function(); 4042 if (target_info.scope()->num_heap_slots() > 0) {
4043 TraceInline(target, "target has context-allocated variables");
4044 return false;
4045 }
4046 FunctionLiteral* function = target_info.function();
3984 4047
3985 // Count the number of AST nodes added by inlining this call. 4048 // Count the number of AST nodes added by inlining this call.
3986 int nodes_added = AstNode::Count() - count_before; 4049 int nodes_added = AstNode::Count() - count_before;
3987 if (FLAG_limit_inlining && nodes_added > kMaxInlinedSize) { 4050 if (FLAG_limit_inlining && nodes_added > kMaxInlinedSize) {
3988 if (FLAG_trace_inlining) TraceInline(target, false); 4051 TraceInline(target, "target AST is too large");
3989 return false; 4052 return false;
3990 } 4053 }
3991 4054
3992 // Check if we can handle all declarations in the inlined functions. 4055 // Check if we can handle all declarations in the inlined functions.
3993 VisitDeclarations(inner_info.scope()->declarations()); 4056 VisitDeclarations(target_info.scope()->declarations());
3994 if (HasStackOverflow()) { 4057 if (HasStackOverflow()) {
4058 TraceInline(target, "target has non-trivial declaration");
3995 ClearStackOverflow(); 4059 ClearStackOverflow();
3996 return false; 4060 return false;
3997 } 4061 }
3998 4062
3999 // Don't inline functions that uses the arguments object or that 4063 // Don't inline functions that uses the arguments object or that
4000 // have a mismatching number of parameters. 4064 // have a mismatching number of parameters.
4001 Handle<SharedFunctionInfo> shared(target->shared()); 4065 Handle<SharedFunctionInfo> target_shared(target->shared());
4002 int arity = expr->arguments()->length(); 4066 int arity = expr->arguments()->length();
4003 if (function->scope()->arguments() != NULL || 4067 if (function->scope()->arguments() != NULL ||
4004 arity != shared->formal_parameter_count()) { 4068 arity != target_shared->formal_parameter_count()) {
4069 TraceInline(target, "target requires special argument handling");
4005 return false; 4070 return false;
4006 } 4071 }
4007 4072
4008 // All statements in the body must be inlineable. 4073 // All statements in the body must be inlineable.
4009 for (int i = 0, count = function->body()->length(); i < count; ++i) { 4074 for (int i = 0, count = function->body()->length(); i < count; ++i) {
4010 if (!function->body()->at(i)->IsInlineable()) return false; 4075 if (!function->body()->at(i)->IsInlineable()) {
4076 TraceInline(target, "target contains unsupported syntax");
4077 return false;
4078 }
4011 } 4079 }
4012 4080
4013 // Generate the deoptimization data for the unoptimized version of 4081 // Generate the deoptimization data for the unoptimized version of
4014 // the target function if we don't already have it. 4082 // the target function if we don't already have it.
4015 if (!shared->has_deoptimization_support()) { 4083 if (!target_shared->has_deoptimization_support()) {
4016 // Note that we compile here using the same AST that we will use for 4084 // Note that we compile here using the same AST that we will use for
4017 // generating the optimized inline code. 4085 // generating the optimized inline code.
4018 inner_info.EnableDeoptimizationSupport(); 4086 target_info.EnableDeoptimizationSupport();
4019 if (!FullCodeGenerator::MakeCode(&inner_info)) return false; 4087 if (!FullCodeGenerator::MakeCode(&target_info)) {
4020 shared->EnableDeoptimizationSupport(*inner_info.code()); 4088 TraceInline(target, "could not generate deoptimization info");
4021 Compiler::RecordFunctionCompilation( 4089 return false;
4022 Logger::FUNCTION_TAG, &inner_info, shared); 4090 }
4091 target_shared->EnableDeoptimizationSupport(*target_info.code());
4092 Compiler::RecordFunctionCompilation(Logger::FUNCTION_TAG,
4093 &target_info,
4094 target_shared);
4023 } 4095 }
4024 4096
4097 // ----------------------------------------------------------------
4025 // Save the pending call context and type feedback oracle. Set up new ones 4098 // Save the pending call context and type feedback oracle. Set up new ones
4026 // for the inlined function. 4099 // for the inlined function.
4027 ASSERT(shared->has_deoptimization_support()); 4100 ASSERT(target_shared->has_deoptimization_support());
4028 AstContext* saved_call_context = call_context(); 4101 TypeFeedbackOracle target_oracle(
4029 HBasicBlock* saved_function_return = function_return(); 4102 Handle<Code>(target_shared->code()),
4030 TypeFeedbackOracle* saved_oracle = oracle();
4031 // On-stack replacement cannot target inlined functions. Since we don't
4032 // use a separate CompilationInfo structure for the inlined function, we
4033 // save and restore the AST ID in the original compilation info.
4034 int saved_osr_ast_id = graph()->info()->osr_ast_id();
4035
4036 TestContext* test_context = NULL;
4037 if (ast_context()->IsTest()) {
4038 // Inlined body is treated as if it occurs in an 'inlined' call context
4039 // with true and false blocks that will forward to the real ones.
4040 HBasicBlock* if_true = graph()->CreateBasicBlock();
4041 HBasicBlock* if_false = graph()->CreateBasicBlock();
4042 if_true->MarkAsInlineReturnTarget();
4043 if_false->MarkAsInlineReturnTarget();
4044 // AstContext constructor pushes on the context stack.
4045 test_context = new TestContext(this, if_true, if_false);
4046 function_return_ = NULL;
4047 } else {
4048 // Inlined body is treated as if it occurs in the original call context.
4049 function_return_ = graph()->CreateBasicBlock();
4050 function_return_->MarkAsInlineReturnTarget();
4051 }
4052 call_context_ = ast_context();
4053 TypeFeedbackOracle new_oracle(
4054 Handle<Code>(shared->code()),
4055 Handle<Context>(target->context()->global_context())); 4103 Handle<Context>(target->context()->global_context()));
4056 oracle_ = &new_oracle; 4104 FunctionState target_state(this, &target_info, &target_oracle);
4057 graph()->info()->SetOsrAstId(AstNode::kNoNumber);
4058 4105
4059 HSubgraph* body = CreateInlinedSubgraph(env, target, function); 4106 HSubgraph* body = CreateInlinedSubgraph(env, target, function);
4060 body->exit_block()->AddInstruction(new HEnterInlined(target, function)); 4107 body->exit_block()->AddInstruction(new HEnterInlined(target, function));
4061 AddToSubgraph(body, function->body()); 4108 AddToSubgraph(body, function->body());
4062 if (HasStackOverflow()) { 4109 if (HasStackOverflow()) {
4063 // Bail out if the inline function did, as we cannot residualize a call 4110 // Bail out if the inline function did, as we cannot residualize a call
4064 // instead. 4111 // instead.
4065 delete test_context; 4112 TraceInline(target, "inline graph construction failed");
4066 call_context_ = saved_call_context;
4067 function_return_ = saved_function_return;
4068 oracle_ = saved_oracle;
4069 graph()->info()->SetOsrAstId(saved_osr_ast_id);
4070 return false; 4113 return false;
4071 } 4114 }
4072 4115
4073 // Update inlined nodes count. 4116 // Update inlined nodes count.
4074 inlined_count_ += nodes_added; 4117 inlined_count_ += nodes_added;
4075 4118
4076 if (FLAG_trace_inlining) TraceInline(target, true); 4119 TraceInline(target, NULL);
4077 4120
4078 if (body->exit_block() != NULL) { 4121 if (body->exit_block() != NULL) {
4079 // Add a return of undefined if control can fall off the body. In a 4122 // Add a return of undefined if control can fall off the body. In a
4080 // test context, undefined is false. 4123 // test context, undefined is false.
4081 HValue* return_value = graph()->GetConstantUndefined(); 4124 HValue* return_value = graph()->GetConstantUndefined();
4082 if (test_context == NULL) { 4125 if (inlined_test_context() == NULL) {
4083 ASSERT(function_return_ != NULL); 4126 ASSERT(function_return() != NULL);
4084 body->exit_block()->AddLeaveInlined(return_value, function_return_); 4127 body->exit_block()->AddLeaveInlined(return_value, function_return());
4085 } else { 4128 } else {
4086 // The graph builder assumes control can reach both branches of a 4129 // The graph builder assumes control can reach both branches of a
4087 // test, so we materialize the undefined value and test it rather than 4130 // test, so we materialize the undefined value and test it rather than
4088 // simply jumping to the false target. 4131 // simply jumping to the false target.
4089 // 4132 //
4090 // TODO(3168478): refactor to avoid this. 4133 // TODO(3168478): refactor to avoid this.
4091 HBasicBlock* empty_true = graph()->CreateBasicBlock(); 4134 HBasicBlock* empty_true = graph()->CreateBasicBlock();
4092 HBasicBlock* empty_false = graph()->CreateBasicBlock(); 4135 HBasicBlock* empty_false = graph()->CreateBasicBlock();
4093 HTest* test = new HTest(return_value, empty_true, empty_false); 4136 HTest* test = new HTest(return_value, empty_true, empty_false);
4094 body->exit_block()->Finish(test); 4137 body->exit_block()->Finish(test);
4095 4138
4096 HValue* const no_return_value = NULL; 4139 HValue* const no_return_value = NULL;
4097 empty_true->AddLeaveInlined(no_return_value, test_context->if_true()); 4140 empty_true->AddLeaveInlined(no_return_value,
4098 empty_false->AddLeaveInlined(no_return_value, test_context->if_false()); 4141 inlined_test_context()->if_true());
4142 empty_false->AddLeaveInlined(no_return_value,
4143 inlined_test_context()->if_false());
4099 } 4144 }
4100 body->set_exit_block(NULL); 4145 body->set_exit_block(NULL);
4101 } 4146 }
4102 4147
4103 // Record the environment at the inlined function call. 4148 // Record the environment at the inlined function call.
4104 AddSimulate(expr->ReturnId()); 4149 AddSimulate(expr->ReturnId());
4105 4150
4106 // Jump to the function entry (without re-recording the environment). 4151 // Jump to the function entry (without re-recording the environment).
4107 current_block()->Finish(new HGoto(body->entry_block())); 4152 current_block()->Finish(new HGoto(body->entry_block()));
4108 4153
4109 // Fix up the function exits. 4154 // Fix up the function exits.
4110 if (test_context != NULL) { 4155 if (inlined_test_context() != NULL) {
4111 HBasicBlock* if_true = test_context->if_true(); 4156 HBasicBlock* if_true = inlined_test_context()->if_true();
4112 HBasicBlock* if_false = test_context->if_false(); 4157 HBasicBlock* if_false = inlined_test_context()->if_false();
4113 if_true->SetJoinId(expr->id()); 4158 if_true->SetJoinId(expr->id());
4114 if_false->SetJoinId(expr->id()); 4159 if_false->SetJoinId(expr->id());
4115 ASSERT(ast_context() == test_context); 4160 ASSERT(ast_context() == inlined_test_context());
4116 delete test_context; // Destructor pops from expression context stack. 4161 // Pop the return test context from the expression context stack.
4162 ClearInlinedTestContext();
4117 4163
4118 // Forward to the real test context. 4164 // Forward to the real test context.
4119 HValue* const no_return_value = NULL; 4165 HValue* const no_return_value = NULL;
4120 HBasicBlock* true_target = TestContext::cast(ast_context())->if_true(); 4166 HBasicBlock* true_target = TestContext::cast(ast_context())->if_true();
4121 if (true_target->IsInlineReturnTarget()) { 4167 if (true_target->IsInlineReturnTarget()) {
4122 if_true->AddLeaveInlined(no_return_value, true_target); 4168 if_true->AddLeaveInlined(no_return_value, true_target);
4123 } else { 4169 } else {
4124 if_true->Goto(true_target); 4170 if_true->Goto(true_target);
4125 } 4171 }
4126 4172
4127 HBasicBlock* false_target = TestContext::cast(ast_context())->if_false(); 4173 HBasicBlock* false_target = TestContext::cast(ast_context())->if_false();
4128 if (false_target->IsInlineReturnTarget()) { 4174 if (false_target->IsInlineReturnTarget()) {
4129 if_false->AddLeaveInlined(no_return_value, false_target); 4175 if_false->AddLeaveInlined(no_return_value, false_target);
4130 } else { 4176 } else {
4131 if_false->Goto(false_target); 4177 if_false->Goto(false_target);
4132 } 4178 }
4133 4179
4134 // TODO(kmillikin): Come up with a better way to handle this. It is too 4180 // TODO(kmillikin): Come up with a better way to handle this. It is too
4135 // subtle. NULL here indicates that the enclosing context has no control 4181 // subtle. NULL here indicates that the enclosing context has no control
4136 // flow to handle. 4182 // flow to handle.
4137 set_current_block(NULL); 4183 set_current_block(NULL);
4138 4184
4139 } else { 4185 } else {
4140 function_return_->SetJoinId(expr->id()); 4186 function_return()->SetJoinId(expr->id());
4141 set_current_block(function_return_); 4187 set_current_block(function_return());
4142 } 4188 }
4143 4189
4144 call_context_ = saved_call_context;
4145 function_return_ = saved_function_return;
4146 oracle_ = saved_oracle;
4147 graph()->info()->SetOsrAstId(saved_osr_ast_id);
4148
4149 return true; 4190 return true;
4150 } 4191 }
4151 4192
4152 4193
4153 void HBasicBlock::AddLeaveInlined(HValue* return_value, HBasicBlock* target) { 4194 void HBasicBlock::AddLeaveInlined(HValue* return_value, HBasicBlock* target) {
4154 ASSERT(target->IsInlineReturnTarget()); 4195 ASSERT(target->IsInlineReturnTarget());
4155 AddInstruction(new HLeaveInlined); 4196 AddInstruction(new HLeaveInlined);
4156 HEnvironment* outer = last_environment()->outer(); 4197 HEnvironment* outer = last_environment()->outer();
4157 if (return_value != NULL) outer->Push(return_value); 4198 if (return_value != NULL) outer->Push(return_value);
4158 UpdateEnvironment(outer); 4199 UpdateEnvironment(outer);
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
4246 } 4287 }
4247 return false; 4288 return false;
4248 } 4289 }
4249 4290
4250 4291
4251 bool HGraphBuilder::TryCallApply(Call* expr) { 4292 bool HGraphBuilder::TryCallApply(Call* expr) {
4252 Expression* callee = expr->expression(); 4293 Expression* callee = expr->expression();
4253 Property* prop = callee->AsProperty(); 4294 Property* prop = callee->AsProperty();
4254 ASSERT(prop != NULL); 4295 ASSERT(prop != NULL);
4255 4296
4256 if (graph()->info()->scope()->arguments() == NULL) return false; 4297 if (info()->scope()->arguments() == NULL) return false;
4257 4298
4258 Handle<String> name = prop->key()->AsLiteral()->AsPropertyName(); 4299 Handle<String> name = prop->key()->AsLiteral()->AsPropertyName();
4259 if (!name->IsEqualTo(CStrVector("apply"))) return false; 4300 if (!name->IsEqualTo(CStrVector("apply"))) return false;
4260 4301
4261 ZoneList<Expression*>* args = expr->arguments(); 4302 ZoneList<Expression*>* args = expr->arguments();
4262 if (args->length() != 2) return false; 4303 if (args->length() != 2) return false;
4263 4304
4264 VariableProxy* arg_two = args->at(1)->AsVariableProxy(); 4305 VariableProxy* arg_two = args->at(1)->AsVariableProxy();
4265 if (arg_two == NULL || !arg_two->var()->IsStackAllocated()) return false; 4306 if (arg_two == NULL || !arg_two->var()->IsStackAllocated()) return false;
4266 HValue* arg_two_value = environment()->Lookup(arg_two->var()); 4307 HValue* arg_two_value = environment()->Lookup(arg_two->var());
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after
4402 4443
4403 if (!global_call) { 4444 if (!global_call) {
4404 ++argument_count; 4445 ++argument_count;
4405 VISIT_FOR_VALUE(expr->expression()); 4446 VISIT_FOR_VALUE(expr->expression());
4406 } 4447 }
4407 4448
4408 if (global_call) { 4449 if (global_call) {
4409 // If there is a global property cell for the name at compile time and 4450 // If there is a global property cell for the name at compile time and
4410 // access check is not enabled we assume that the function will not change 4451 // access check is not enabled we assume that the function will not change
4411 // and generate optimized code for calling the function. 4452 // and generate optimized code for calling the function.
4412 CompilationInfo* info = graph()->info(); 4453 bool known_global_function = info()->has_global_object() &&
4413 bool known_global_function = info->has_global_object() && 4454 !info()->global_object()->IsAccessCheckNeeded() &&
4414 !info->global_object()->IsAccessCheckNeeded() && 4455 expr->ComputeGlobalTarget(Handle<GlobalObject>(info()->global_object() ),
4415 expr->ComputeGlobalTarget(Handle<GlobalObject>(info->global_object()),
4416 var->name()); 4456 var->name());
4417 if (known_global_function) { 4457 if (known_global_function) {
4418 // Push the global object instead of the global receiver because 4458 // Push the global object instead of the global receiver because
4419 // code generated by the full code generator expects it. 4459 // code generated by the full code generator expects it.
4420 HContext* context = new HContext; 4460 HContext* context = new HContext;
4421 HGlobalObject* global_object = new HGlobalObject(context); 4461 HGlobalObject* global_object = new HGlobalObject(context);
4422 AddInstruction(context); 4462 AddInstruction(context);
4423 PushAndAdd(global_object); 4463 PushAndAdd(global_object);
4424 VisitExpressions(expr->arguments()); 4464 VisitExpressions(expr->arguments());
4425 CHECK_BAILOUT; 4465 CHECK_BAILOUT;
(...skipping 609 matching lines...) Expand 10 before | Expand all | Expand 10 after
5035 return; 5075 return;
5036 } 5076 }
5037 5077
5038 VISIT_FOR_VALUE(expr->left()); 5078 VISIT_FOR_VALUE(expr->left());
5039 VISIT_FOR_VALUE(expr->right()); 5079 VISIT_FOR_VALUE(expr->right());
5040 5080
5041 HValue* right = Pop(); 5081 HValue* right = Pop();
5042 HValue* left = Pop(); 5082 HValue* left = Pop();
5043 Token::Value op = expr->op(); 5083 Token::Value op = expr->op();
5044 5084
5045 TypeInfo info = oracle()->CompareType(expr); 5085 TypeInfo type_info = oracle()->CompareType(expr);
5046 HInstruction* instr = NULL; 5086 HInstruction* instr = NULL;
5047 if (op == Token::INSTANCEOF) { 5087 if (op == Token::INSTANCEOF) {
5048 // Check to see if the rhs of the instanceof is a global function not 5088 // Check to see if the rhs of the instanceof is a global function not
5049 // residing in new space. If it is we assume that the function will stay the 5089 // residing in new space. If it is we assume that the function will stay the
5050 // same. 5090 // same.
5051 Handle<JSFunction> target = Handle<JSFunction>::null(); 5091 Handle<JSFunction> target = Handle<JSFunction>::null();
5052 Variable* var = expr->right()->AsVariableProxy()->AsVariable(); 5092 Variable* var = expr->right()->AsVariableProxy()->AsVariable();
5053 bool global_function = (var != NULL) && var->is_global() && !var->is_this(); 5093 bool global_function = (var != NULL) && var->is_global() && !var->is_this();
5054 CompilationInfo* info = graph()->info();
5055 if (global_function && 5094 if (global_function &&
5056 info->has_global_object() && 5095 info()->has_global_object() &&
5057 !info->global_object()->IsAccessCheckNeeded()) { 5096 !info()->global_object()->IsAccessCheckNeeded()) {
5058 Handle<String> name = var->name(); 5097 Handle<String> name = var->name();
5059 Handle<GlobalObject> global(info->global_object()); 5098 Handle<GlobalObject> global(info()->global_object());
5060 LookupResult lookup; 5099 LookupResult lookup;
5061 global->Lookup(*name, &lookup); 5100 global->Lookup(*name, &lookup);
5062 if (lookup.IsProperty() && 5101 if (lookup.IsProperty() &&
5063 lookup.type() == NORMAL && 5102 lookup.type() == NORMAL &&
5064 lookup.GetValue()->IsJSFunction()) { 5103 lookup.GetValue()->IsJSFunction()) {
5065 Handle<JSFunction> candidate(JSFunction::cast(lookup.GetValue())); 5104 Handle<JSFunction> candidate(JSFunction::cast(lookup.GetValue()));
5066 // If the function is in new space we assume it's more likely to 5105 // If the function is in new space we assume it's more likely to
5067 // change and thus prefer the general IC code. 5106 // change and thus prefer the general IC code.
5068 if (!Heap::InNewSpace(*candidate)) { 5107 if (!Heap::InNewSpace(*candidate)) {
5069 target = candidate; 5108 target = candidate;
5070 } 5109 }
5071 } 5110 }
5072 } 5111 }
5073 5112
5074 // If the target is not null we have found a known global function that is 5113 // If the target is not null we have found a known global function that is
5075 // assumed to stay the same for this instanceof. 5114 // assumed to stay the same for this instanceof.
5076 if (target.is_null()) { 5115 if (target.is_null()) {
5077 HContext* context = new HContext; 5116 HContext* context = new HContext;
5078 AddInstruction(context); 5117 AddInstruction(context);
5079 instr = new HInstanceOf(context, left, right); 5118 instr = new HInstanceOf(context, left, right);
5080 } else { 5119 } else {
5081 AddInstruction(new HCheckFunction(right, target)); 5120 AddInstruction(new HCheckFunction(right, target));
5082 instr = new HInstanceOfKnownGlobal(left, target); 5121 instr = new HInstanceOfKnownGlobal(left, target);
5083 } 5122 }
5084 } else if (op == Token::IN) { 5123 } else if (op == Token::IN) {
5085 BAILOUT("Unsupported comparison: in"); 5124 BAILOUT("Unsupported comparison: in");
5086 } else if (info.IsNonPrimitive()) { 5125 } else if (type_info.IsNonPrimitive()) {
5087 switch (op) { 5126 switch (op) {
5088 case Token::EQ: 5127 case Token::EQ:
5089 case Token::EQ_STRICT: { 5128 case Token::EQ_STRICT: {
5090 AddInstruction(new HCheckNonSmi(left)); 5129 AddInstruction(new HCheckNonSmi(left));
5091 AddInstruction(HCheckInstanceType::NewIsJSObjectOrJSFunction(left)); 5130 AddInstruction(HCheckInstanceType::NewIsJSObjectOrJSFunction(left));
5092 AddInstruction(new HCheckNonSmi(right)); 5131 AddInstruction(new HCheckNonSmi(right));
5093 AddInstruction(HCheckInstanceType::NewIsJSObjectOrJSFunction(right)); 5132 AddInstruction(HCheckInstanceType::NewIsJSObjectOrJSFunction(right));
5094 instr = new HCompareJSObjectEq(left, right); 5133 instr = new HCompareJSObjectEq(left, right);
5095 break; 5134 break;
5096 } 5135 }
5097 default: 5136 default:
5098 BAILOUT("Unsupported non-primitive compare"); 5137 BAILOUT("Unsupported non-primitive compare");
5099 break; 5138 break;
5100 } 5139 }
5101 } else { 5140 } else {
5102 HCompare* compare = new HCompare(left, right, op); 5141 HCompare* compare = new HCompare(left, right, op);
5103 Representation r = ToRepresentation(info); 5142 Representation r = ToRepresentation(type_info);
5104 compare->SetInputRepresentation(r); 5143 compare->SetInputRepresentation(r);
5105 instr = compare; 5144 instr = compare;
5106 } 5145 }
5107 instr->set_position(expr->position()); 5146 instr->set_position(expr->position());
5108 ast_context()->ReturnInstruction(instr, expr->id()); 5147 ast_context()->ReturnInstruction(instr, expr->id());
5109 } 5148 }
5110 5149
5111 5150
5112 void HGraphBuilder::VisitCompareToNull(CompareToNull* expr) { 5151 void HGraphBuilder::VisitCompareToNull(CompareToNull* expr) {
5113 VISIT_FOR_VALUE(expr->expression()); 5152 VISIT_FOR_VALUE(expr->expression());
(...skipping 892 matching lines...) Expand 10 before | Expand all | Expand 10 after
6006 } 6045 }
6007 } 6046 }
6008 6047
6009 #ifdef DEBUG 6048 #ifdef DEBUG
6010 if (graph_ != NULL) graph_->Verify(); 6049 if (graph_ != NULL) graph_->Verify();
6011 if (allocator_ != NULL) allocator_->Verify(); 6050 if (allocator_ != NULL) allocator_->Verify();
6012 #endif 6051 #endif
6013 } 6052 }
6014 6053
6015 } } // namespace v8::internal 6054 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/hydrogen.h ('k') | src/ia32/lithium-codegen-ia32.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698