| OLD | NEW |
| 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 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 68 first_instruction_index_(-1), | 68 first_instruction_index_(-1), |
| 69 last_instruction_index_(-1), | 69 last_instruction_index_(-1), |
| 70 deleted_phis_(4), | 70 deleted_phis_(4), |
| 71 parent_loop_header_(NULL), | 71 parent_loop_header_(NULL), |
| 72 is_inline_return_target_(false) { | 72 is_inline_return_target_(false) { |
| 73 } | 73 } |
| 74 | 74 |
| 75 | 75 |
| 76 void HBasicBlock::AttachLoopInformation() { | 76 void HBasicBlock::AttachLoopInformation() { |
| 77 ASSERT(!IsLoopHeader()); | 77 ASSERT(!IsLoopHeader()); |
| 78 loop_information_ = new HLoopInformation(this); | 78 loop_information_ = new(zone()) HLoopInformation(this); |
| 79 } | 79 } |
| 80 | 80 |
| 81 | 81 |
| 82 void HBasicBlock::DetachLoopInformation() { | 82 void HBasicBlock::DetachLoopInformation() { |
| 83 ASSERT(IsLoopHeader()); | 83 ASSERT(IsLoopHeader()); |
| 84 loop_information_ = NULL; | 84 loop_information_ = NULL; |
| 85 } | 85 } |
| 86 | 86 |
| 87 | 87 |
| 88 void HBasicBlock::AddPhi(HPhi* phi) { | 88 void HBasicBlock::AddPhi(HPhi* phi) { |
| (...skipping 11 matching lines...) Expand all Loading... |
| 100 phis_.RemoveElement(phi); | 100 phis_.RemoveElement(phi); |
| 101 phi->SetBlock(NULL); | 101 phi->SetBlock(NULL); |
| 102 } | 102 } |
| 103 | 103 |
| 104 | 104 |
| 105 void HBasicBlock::AddInstruction(HInstruction* instr) { | 105 void HBasicBlock::AddInstruction(HInstruction* instr) { |
| 106 ASSERT(!IsStartBlock() || !IsFinished()); | 106 ASSERT(!IsStartBlock() || !IsFinished()); |
| 107 ASSERT(!instr->IsLinked()); | 107 ASSERT(!instr->IsLinked()); |
| 108 ASSERT(!IsFinished()); | 108 ASSERT(!IsFinished()); |
| 109 if (first_ == NULL) { | 109 if (first_ == NULL) { |
| 110 HBlockEntry* entry = new HBlockEntry(); | 110 HBlockEntry* entry = new(zone()) HBlockEntry(); |
| 111 entry->InitializeAsFirst(this); | 111 entry->InitializeAsFirst(this); |
| 112 first_ = last_ = entry; | 112 first_ = last_ = entry; |
| 113 } | 113 } |
| 114 instr->InsertAfter(last_); | 114 instr->InsertAfter(last_); |
| 115 last_ = instr; | 115 last_ = instr; |
| 116 } | 116 } |
| 117 | 117 |
| 118 | 118 |
| 119 HDeoptimize* HBasicBlock::CreateDeoptimize() { | 119 HDeoptimize* HBasicBlock::CreateDeoptimize() { |
| 120 ASSERT(HasEnvironment()); | 120 ASSERT(HasEnvironment()); |
| 121 HEnvironment* environment = last_environment(); | 121 HEnvironment* environment = last_environment(); |
| 122 | 122 |
| 123 HDeoptimize* instr = new HDeoptimize(environment->length()); | 123 HDeoptimize* instr = new(zone()) HDeoptimize(environment->length()); |
| 124 | 124 |
| 125 for (int i = 0; i < environment->length(); i++) { | 125 for (int i = 0; i < environment->length(); i++) { |
| 126 HValue* val = environment->values()->at(i); | 126 HValue* val = environment->values()->at(i); |
| 127 instr->AddEnvironmentValue(val); | 127 instr->AddEnvironmentValue(val); |
| 128 } | 128 } |
| 129 | 129 |
| 130 return instr; | 130 return instr; |
| 131 } | 131 } |
| 132 | 132 |
| 133 | 133 |
| 134 HSimulate* HBasicBlock::CreateSimulate(int id) { | 134 HSimulate* HBasicBlock::CreateSimulate(int id) { |
| 135 ASSERT(HasEnvironment()); | 135 ASSERT(HasEnvironment()); |
| 136 HEnvironment* environment = last_environment(); | 136 HEnvironment* environment = last_environment(); |
| 137 ASSERT(id == AstNode::kNoNumber || | 137 ASSERT(id == AstNode::kNoNumber || |
| 138 environment->closure()->shared()->VerifyBailoutId(id)); | 138 environment->closure()->shared()->VerifyBailoutId(id)); |
| 139 | 139 |
| 140 int push_count = environment->push_count(); | 140 int push_count = environment->push_count(); |
| 141 int pop_count = environment->pop_count(); | 141 int pop_count = environment->pop_count(); |
| 142 | 142 |
| 143 int length = environment->length(); | 143 HSimulate* instr = new(zone()) HSimulate(id, pop_count); |
| 144 HSimulate* instr = new HSimulate(id, pop_count, length); | |
| 145 for (int i = push_count - 1; i >= 0; --i) { | 144 for (int i = push_count - 1; i >= 0; --i) { |
| 146 instr->AddPushedValue(environment->ExpressionStackAt(i)); | 145 instr->AddPushedValue(environment->ExpressionStackAt(i)); |
| 147 } | 146 } |
| 148 for (int i = 0; i < environment->assigned_variables()->length(); ++i) { | 147 for (int i = 0; i < environment->assigned_variables()->length(); ++i) { |
| 149 int index = environment->assigned_variables()->at(i); | 148 int index = environment->assigned_variables()->at(i); |
| 150 instr->AddAssignedValue(index, environment->Lookup(index)); | 149 instr->AddAssignedValue(index, environment->Lookup(index)); |
| 151 } | 150 } |
| 152 environment->ClearHistory(); | 151 environment->ClearHistory(); |
| 153 return instr; | 152 return instr; |
| 154 } | 153 } |
| 155 | 154 |
| 156 | 155 |
| 157 void HBasicBlock::Finish(HControlInstruction* end) { | 156 void HBasicBlock::Finish(HControlInstruction* end) { |
| 158 ASSERT(!IsFinished()); | 157 ASSERT(!IsFinished()); |
| 159 AddInstruction(end); | 158 AddInstruction(end); |
| 160 end_ = end; | 159 end_ = end; |
| 161 if (end->FirstSuccessor() != NULL) { | 160 if (end->FirstSuccessor() != NULL) { |
| 162 end->FirstSuccessor()->RegisterPredecessor(this); | 161 end->FirstSuccessor()->RegisterPredecessor(this); |
| 163 if (end->SecondSuccessor() != NULL) { | 162 if (end->SecondSuccessor() != NULL) { |
| 164 end->SecondSuccessor()->RegisterPredecessor(this); | 163 end->SecondSuccessor()->RegisterPredecessor(this); |
| 165 } | 164 } |
| 166 } | 165 } |
| 167 } | 166 } |
| 168 | 167 |
| 169 | 168 |
| 170 void HBasicBlock::Goto(HBasicBlock* block, bool include_stack_check) { | 169 void HBasicBlock::Goto(HBasicBlock* block, bool include_stack_check) { |
| 171 if (block->IsInlineReturnTarget()) { | 170 if (block->IsInlineReturnTarget()) { |
| 172 AddInstruction(new HLeaveInlined); | 171 AddInstruction(new(zone()) HLeaveInlined); |
| 173 last_environment_ = last_environment()->outer(); | 172 last_environment_ = last_environment()->outer(); |
| 174 } | 173 } |
| 175 AddSimulate(AstNode::kNoNumber); | 174 AddSimulate(AstNode::kNoNumber); |
| 176 HGoto* instr = new HGoto(block); | 175 HGoto* instr = new(zone()) HGoto(block); |
| 177 instr->set_include_stack_check(include_stack_check); | 176 instr->set_include_stack_check(include_stack_check); |
| 178 Finish(instr); | 177 Finish(instr); |
| 179 } | 178 } |
| 180 | 179 |
| 181 | 180 |
| 182 void HBasicBlock::AddLeaveInlined(HValue* return_value, HBasicBlock* target) { | 181 void HBasicBlock::AddLeaveInlined(HValue* return_value, HBasicBlock* target) { |
| 183 ASSERT(target->IsInlineReturnTarget()); | 182 ASSERT(target->IsInlineReturnTarget()); |
| 184 ASSERT(return_value != NULL); | 183 ASSERT(return_value != NULL); |
| 185 AddInstruction(new HLeaveInlined); | 184 AddInstruction(new(zone()) HLeaveInlined); |
| 186 last_environment_ = last_environment()->outer(); | 185 last_environment_ = last_environment()->outer(); |
| 187 last_environment()->Push(return_value); | 186 last_environment()->Push(return_value); |
| 188 AddSimulate(AstNode::kNoNumber); | 187 AddSimulate(AstNode::kNoNumber); |
| 189 HGoto* instr = new HGoto(target); | 188 HGoto* instr = new(zone()) HGoto(target); |
| 190 Finish(instr); | 189 Finish(instr); |
| 191 } | 190 } |
| 192 | 191 |
| 193 | 192 |
| 194 void HBasicBlock::SetInitialEnvironment(HEnvironment* env) { | 193 void HBasicBlock::SetInitialEnvironment(HEnvironment* env) { |
| 195 ASSERT(!HasEnvironment()); | 194 ASSERT(!HasEnvironment()); |
| 196 ASSERT(first() == NULL); | 195 ASSERT(first() == NULL); |
| 197 UpdateEnvironment(env); | 196 UpdateEnvironment(env); |
| 198 } | 197 } |
| 199 | 198 |
| (...skipping 287 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 487 } | 486 } |
| 488 } | 487 } |
| 489 } | 488 } |
| 490 | 489 |
| 491 #endif | 490 #endif |
| 492 | 491 |
| 493 | 492 |
| 494 HConstant* HGraph::GetConstant(SetOncePointer<HConstant>* pointer, | 493 HConstant* HGraph::GetConstant(SetOncePointer<HConstant>* pointer, |
| 495 Object* value) { | 494 Object* value) { |
| 496 if (!pointer->is_set()) { | 495 if (!pointer->is_set()) { |
| 497 HConstant* constant = new HConstant(Handle<Object>(value), | 496 HConstant* constant = new(zone()) HConstant(Handle<Object>(value), |
| 498 Representation::Tagged()); | 497 Representation::Tagged()); |
| 499 constant->InsertAfter(GetConstantUndefined()); | 498 constant->InsertAfter(GetConstantUndefined()); |
| 500 pointer->set(constant); | 499 pointer->set(constant); |
| 501 } | 500 } |
| 502 return pointer->get(); | 501 return pointer->get(); |
| 503 } | 502 } |
| 504 | 503 |
| 505 | 504 |
| 506 HConstant* HGraph::GetConstant1() { | 505 HConstant* HGraph::GetConstant1() { |
| 507 return GetConstant(&constant_1_, Smi::FromInt(1)); | 506 return GetConstant(&constant_1_, Smi::FromInt(1)); |
| 508 } | 507 } |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 574 } | 573 } |
| 575 | 574 |
| 576 | 575 |
| 577 HGraph::HGraph(CompilationInfo* info) | 576 HGraph::HGraph(CompilationInfo* info) |
| 578 : isolate_(info->isolate()), | 577 : isolate_(info->isolate()), |
| 579 next_block_id_(0), | 578 next_block_id_(0), |
| 580 entry_block_(NULL), | 579 entry_block_(NULL), |
| 581 blocks_(8), | 580 blocks_(8), |
| 582 values_(16), | 581 values_(16), |
| 583 phi_list_(NULL) { | 582 phi_list_(NULL) { |
| 584 start_environment_ = new HEnvironment(NULL, info->scope(), info->closure()); | 583 start_environment_ = |
| 584 new(zone()) HEnvironment(NULL, info->scope(), info->closure()); |
| 585 start_environment_->set_ast_id(info->function()->id()); | 585 start_environment_->set_ast_id(info->function()->id()); |
| 586 entry_block_ = CreateBasicBlock(); | 586 entry_block_ = CreateBasicBlock(); |
| 587 entry_block_->SetInitialEnvironment(start_environment_); | 587 entry_block_->SetInitialEnvironment(start_environment_); |
| 588 } | 588 } |
| 589 | 589 |
| 590 | 590 |
| 591 Handle<Code> HGraph::Compile(CompilationInfo* info) { | 591 Handle<Code> HGraph::Compile(CompilationInfo* info) { |
| 592 int values = GetMaximumValueID(); | 592 int values = GetMaximumValueID(); |
| 593 if (values > LAllocator::max_initial_value_ids()) { | 593 if (values > LAllocator::max_initial_value_ids()) { |
| 594 if (FLAG_trace_bailout) PrintF("Function is too big\n"); | 594 if (FLAG_trace_bailout) PrintF("Function is too big\n"); |
| (...skipping 29 matching lines...) Expand all Loading... |
| 624 CodeGenerator::MakeCodeEpilogue(&assembler, flags, info); | 624 CodeGenerator::MakeCodeEpilogue(&assembler, flags, info); |
| 625 generator.FinishCode(code); | 625 generator.FinishCode(code); |
| 626 CodeGenerator::PrintCode(code, info); | 626 CodeGenerator::PrintCode(code, info); |
| 627 return code; | 627 return code; |
| 628 } | 628 } |
| 629 return Handle<Code>::null(); | 629 return Handle<Code>::null(); |
| 630 } | 630 } |
| 631 | 631 |
| 632 | 632 |
| 633 HBasicBlock* HGraph::CreateBasicBlock() { | 633 HBasicBlock* HGraph::CreateBasicBlock() { |
| 634 HBasicBlock* result = new HBasicBlock(this); | 634 HBasicBlock* result = new(zone()) HBasicBlock(this); |
| 635 blocks_.Add(result); | 635 blocks_.Add(result); |
| 636 return result; | 636 return result; |
| 637 } | 637 } |
| 638 | 638 |
| 639 | 639 |
| 640 void HGraph::Canonicalize() { | 640 void HGraph::Canonicalize() { |
| 641 if (!FLAG_use_canonicalizing) return; | 641 if (!FLAG_use_canonicalizing) return; |
| 642 HPhase phase("Canonicalize", this); | 642 HPhase phase("Canonicalize", this); |
| 643 for (int i = 0; i < blocks()->length(); ++i) { | 643 for (int i = 0; i < blocks()->length(); ++i) { |
| 644 HInstruction* instr = blocks()->at(i)->first(); | 644 HInstruction* instr = blocks()->at(i)->first(); |
| (...skipping 621 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1266 void ComputeBlockSideEffects(); | 1266 void ComputeBlockSideEffects(); |
| 1267 void LoopInvariantCodeMotion(); | 1267 void LoopInvariantCodeMotion(); |
| 1268 void ProcessLoopBlock(HBasicBlock* block, | 1268 void ProcessLoopBlock(HBasicBlock* block, |
| 1269 HBasicBlock* before_loop, | 1269 HBasicBlock* before_loop, |
| 1270 int loop_kills); | 1270 int loop_kills); |
| 1271 bool AllowCodeMotion(); | 1271 bool AllowCodeMotion(); |
| 1272 bool ShouldMove(HInstruction* instr, HBasicBlock* loop_header); | 1272 bool ShouldMove(HInstruction* instr, HBasicBlock* loop_header); |
| 1273 | 1273 |
| 1274 HGraph* graph() { return graph_; } | 1274 HGraph* graph() { return graph_; } |
| 1275 CompilationInfo* info() { return info_; } | 1275 CompilationInfo* info() { return info_; } |
| 1276 Zone* zone() { return graph_->zone(); } |
| 1276 | 1277 |
| 1277 HGraph* graph_; | 1278 HGraph* graph_; |
| 1278 CompilationInfo* info_; | 1279 CompilationInfo* info_; |
| 1279 | 1280 |
| 1280 // A map of block IDs to their side effects. | 1281 // A map of block IDs to their side effects. |
| 1281 ZoneList<int> block_side_effects_; | 1282 ZoneList<int> block_side_effects_; |
| 1282 | 1283 |
| 1283 // A map of loop header block IDs to their loop's side effects. | 1284 // A map of loop header block IDs to their loop's side effects. |
| 1284 ZoneList<int> loop_side_effects_; | 1285 ZoneList<int> loop_side_effects_; |
| 1285 }; | 1286 }; |
| 1286 | 1287 |
| 1287 | 1288 |
| 1288 void HGlobalValueNumberer::Analyze() { | 1289 void HGlobalValueNumberer::Analyze() { |
| 1289 ComputeBlockSideEffects(); | 1290 ComputeBlockSideEffects(); |
| 1290 if (FLAG_loop_invariant_code_motion) { | 1291 if (FLAG_loop_invariant_code_motion) { |
| 1291 LoopInvariantCodeMotion(); | 1292 LoopInvariantCodeMotion(); |
| 1292 } | 1293 } |
| 1293 HValueMap* map = new HValueMap(); | 1294 HValueMap* map = new(zone()) HValueMap(); |
| 1294 AnalyzeBlock(graph_->blocks()->at(0), map); | 1295 AnalyzeBlock(graph_->blocks()->at(0), map); |
| 1295 } | 1296 } |
| 1296 | 1297 |
| 1297 | 1298 |
| 1298 void HGlobalValueNumberer::ComputeBlockSideEffects() { | 1299 void HGlobalValueNumberer::ComputeBlockSideEffects() { |
| 1299 for (int i = graph_->blocks()->length() - 1; i >= 0; --i) { | 1300 for (int i = graph_->blocks()->length() - 1; i >= 0; --i) { |
| 1300 // Compute side effects for the block. | 1301 // Compute side effects for the block. |
| 1301 HBasicBlock* block = graph_->blocks()->at(i); | 1302 HBasicBlock* block = graph_->blocks()->at(i); |
| 1302 HInstruction* instr = block->first(); | 1303 HInstruction* instr = block->first(); |
| 1303 int id = block->block_id(); | 1304 int id = block->block_id(); |
| (...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1450 } | 1451 } |
| 1451 } | 1452 } |
| 1452 instr = next; | 1453 instr = next; |
| 1453 } | 1454 } |
| 1454 | 1455 |
| 1455 // Recursively continue analysis for all immediately dominated blocks. | 1456 // Recursively continue analysis for all immediately dominated blocks. |
| 1456 int length = block->dominated_blocks()->length(); | 1457 int length = block->dominated_blocks()->length(); |
| 1457 for (int i = 0; i < length; ++i) { | 1458 for (int i = 0; i < length; ++i) { |
| 1458 HBasicBlock* dominated = block->dominated_blocks()->at(i); | 1459 HBasicBlock* dominated = block->dominated_blocks()->at(i); |
| 1459 // No need to copy the map for the last child in the dominator tree. | 1460 // No need to copy the map for the last child in the dominator tree. |
| 1460 HValueMap* successor_map = (i == length - 1) ? map : map->Copy(); | 1461 HValueMap* successor_map = (i == length - 1) ? map : map->Copy(zone()); |
| 1461 | 1462 |
| 1462 // If the dominated block is not a successor to this block we have to | 1463 // If the dominated block is not a successor to this block we have to |
| 1463 // kill everything killed on any path between this block and the | 1464 // kill everything killed on any path between this block and the |
| 1464 // dominated block. Note we rely on the block ordering. | 1465 // dominated block. Note we rely on the block ordering. |
| 1465 bool is_successor = false; | 1466 bool is_successor = false; |
| 1466 int predecessor_count = dominated->predecessors()->length(); | 1467 int predecessor_count = dominated->predecessors()->length(); |
| 1467 for (int j = 0; !is_successor && j < predecessor_count; ++j) { | 1468 for (int j = 0; !is_successor && j < predecessor_count; ++j) { |
| 1468 is_successor = (dominated->predecessors()->at(j) == block); | 1469 is_successor = (dominated->predecessors()->at(j) == block); |
| 1469 } | 1470 } |
| 1470 | 1471 |
| (...skipping 17 matching lines...) Expand all Loading... |
| 1488 | 1489 |
| 1489 void Analyze(); | 1490 void Analyze(); |
| 1490 | 1491 |
| 1491 private: | 1492 private: |
| 1492 Representation TryChange(HValue* current); | 1493 Representation TryChange(HValue* current); |
| 1493 void AddToWorklist(HValue* current); | 1494 void AddToWorklist(HValue* current); |
| 1494 void InferBasedOnInputs(HValue* current); | 1495 void InferBasedOnInputs(HValue* current); |
| 1495 void AddDependantsToWorklist(HValue* current); | 1496 void AddDependantsToWorklist(HValue* current); |
| 1496 void InferBasedOnUses(HValue* current); | 1497 void InferBasedOnUses(HValue* current); |
| 1497 | 1498 |
| 1499 Zone* zone() { return graph_->zone(); } |
| 1500 |
| 1498 HGraph* graph_; | 1501 HGraph* graph_; |
| 1499 ZoneList<HValue*> worklist_; | 1502 ZoneList<HValue*> worklist_; |
| 1500 BitVector in_worklist_; | 1503 BitVector in_worklist_; |
| 1501 }; | 1504 }; |
| 1502 | 1505 |
| 1503 | 1506 |
| 1504 void HInferRepresentation::AddToWorklist(HValue* current) { | 1507 void HInferRepresentation::AddToWorklist(HValue* current) { |
| 1505 if (current->representation().IsSpecialization()) return; | 1508 if (current->representation().IsSpecialization()) return; |
| 1506 if (!current->CheckFlag(HValue::kFlexibleRepresentation)) return; | 1509 if (!current->CheckFlag(HValue::kFlexibleRepresentation)) return; |
| 1507 if (in_worklist_.Contains(current->id())) return; | 1510 if (in_worklist_.Contains(current->id())) return; |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1599 void HInferRepresentation::Analyze() { | 1602 void HInferRepresentation::Analyze() { |
| 1600 HPhase phase("Infer representations", graph_); | 1603 HPhase phase("Infer representations", graph_); |
| 1601 | 1604 |
| 1602 // (1) Initialize bit vectors and count real uses. Each phi | 1605 // (1) Initialize bit vectors and count real uses. Each phi |
| 1603 // gets a bit-vector of length <number of phis>. | 1606 // gets a bit-vector of length <number of phis>. |
| 1604 const ZoneList<HPhi*>* phi_list = graph_->phi_list(); | 1607 const ZoneList<HPhi*>* phi_list = graph_->phi_list(); |
| 1605 int num_phis = phi_list->length(); | 1608 int num_phis = phi_list->length(); |
| 1606 ScopedVector<BitVector*> connected_phis(num_phis); | 1609 ScopedVector<BitVector*> connected_phis(num_phis); |
| 1607 for (int i = 0; i < num_phis; i++) { | 1610 for (int i = 0; i < num_phis; i++) { |
| 1608 phi_list->at(i)->InitRealUses(i); | 1611 phi_list->at(i)->InitRealUses(i); |
| 1609 connected_phis[i] = new BitVector(num_phis); | 1612 connected_phis[i] = new(zone()) BitVector(num_phis); |
| 1610 connected_phis[i]->Add(i); | 1613 connected_phis[i]->Add(i); |
| 1611 } | 1614 } |
| 1612 | 1615 |
| 1613 // (2) Do a fixed point iteration to find the set of connected phis. | 1616 // (2) Do a fixed point iteration to find the set of connected phis. |
| 1614 // A phi is connected to another phi if its value is used either | 1617 // A phi is connected to another phi if its value is used either |
| 1615 // directly or indirectly through a transitive closure of the def-use | 1618 // directly or indirectly through a transitive closure of the def-use |
| 1616 // relation. | 1619 // relation. |
| 1617 bool change = true; | 1620 bool change = true; |
| 1618 while (change) { | 1621 while (change) { |
| 1619 change = false; | 1622 change = false; |
| (...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1764 bool is_truncating = use->CheckFlag(HValue::kTruncatingToInt32); | 1767 bool is_truncating = use->CheckFlag(HValue::kTruncatingToInt32); |
| 1765 if (value->IsConstant()) { | 1768 if (value->IsConstant()) { |
| 1766 HConstant* constant = HConstant::cast(value); | 1769 HConstant* constant = HConstant::cast(value); |
| 1767 // Try to create a new copy of the constant with the new representation. | 1770 // Try to create a new copy of the constant with the new representation. |
| 1768 new_value = is_truncating | 1771 new_value = is_truncating |
| 1769 ? constant->CopyToTruncatedInt32() | 1772 ? constant->CopyToTruncatedInt32() |
| 1770 : constant->CopyToRepresentation(to); | 1773 : constant->CopyToRepresentation(to); |
| 1771 } | 1774 } |
| 1772 | 1775 |
| 1773 if (new_value == NULL) { | 1776 if (new_value == NULL) { |
| 1774 new_value = new HChange(value, value->representation(), to, is_truncating); | 1777 new_value = |
| 1778 new(zone()) HChange(value, value->representation(), to, is_truncating); |
| 1775 } | 1779 } |
| 1776 | 1780 |
| 1777 new_value->InsertBefore(next); | 1781 new_value->InsertBefore(next); |
| 1778 value->ReplaceFirstAtUse(use, new_value, to); | 1782 value->ReplaceFirstAtUse(use, new_value, to); |
| 1779 } | 1783 } |
| 1780 | 1784 |
| 1781 | 1785 |
| 1782 int CompareConversionUses(HValue* a, | 1786 int CompareConversionUses(HValue* a, |
| 1783 HValue* b, | 1787 HValue* b, |
| 1784 Representation a_rep, | 1788 Representation a_rep, |
| (...skipping 270 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2055 | 2059 |
| 2056 | 2060 |
| 2057 void TestContext::BuildBranch(HValue* value) { | 2061 void TestContext::BuildBranch(HValue* value) { |
| 2058 // We expect the graph to be in edge-split form: there is no edge that | 2062 // We expect the graph to be in edge-split form: there is no edge that |
| 2059 // connects a branch node to a join node. We conservatively ensure that | 2063 // connects a branch node to a join node. We conservatively ensure that |
| 2060 // property by always adding an empty block on the outgoing edges of this | 2064 // property by always adding an empty block on the outgoing edges of this |
| 2061 // branch. | 2065 // branch. |
| 2062 HGraphBuilder* builder = owner(); | 2066 HGraphBuilder* builder = owner(); |
| 2063 HBasicBlock* empty_true = builder->graph()->CreateBasicBlock(); | 2067 HBasicBlock* empty_true = builder->graph()->CreateBasicBlock(); |
| 2064 HBasicBlock* empty_false = builder->graph()->CreateBasicBlock(); | 2068 HBasicBlock* empty_false = builder->graph()->CreateBasicBlock(); |
| 2065 HTest* test = new HTest(value, empty_true, empty_false); | 2069 HTest* test = new(zone()) HTest(value, empty_true, empty_false); |
| 2066 builder->current_block()->Finish(test); | 2070 builder->current_block()->Finish(test); |
| 2067 | 2071 |
| 2068 empty_true->Goto(if_true(), false); | 2072 empty_true->Goto(if_true(), false); |
| 2069 empty_false->Goto(if_false(), false); | 2073 empty_false->Goto(if_false(), false); |
| 2070 builder->set_current_block(NULL); | 2074 builder->set_current_block(NULL); |
| 2071 } | 2075 } |
| 2072 | 2076 |
| 2073 | 2077 |
| 2074 // HGraphBuilder infrastructure for bailing out and checking bailouts. | 2078 // HGraphBuilder infrastructure for bailing out and checking bailouts. |
| 2075 #define BAILOUT(reason) \ | 2079 #define BAILOUT(reason) \ |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2138 void HGraphBuilder::VisitForControl(Expression* expr, | 2142 void HGraphBuilder::VisitForControl(Expression* expr, |
| 2139 HBasicBlock* true_block, | 2143 HBasicBlock* true_block, |
| 2140 HBasicBlock* false_block) { | 2144 HBasicBlock* false_block) { |
| 2141 TestContext for_test(this, true_block, false_block); | 2145 TestContext for_test(this, true_block, false_block); |
| 2142 Visit(expr); | 2146 Visit(expr); |
| 2143 } | 2147 } |
| 2144 | 2148 |
| 2145 | 2149 |
| 2146 void HGraphBuilder::VisitArgument(Expression* expr) { | 2150 void HGraphBuilder::VisitArgument(Expression* expr) { |
| 2147 VISIT_FOR_VALUE(expr); | 2151 VISIT_FOR_VALUE(expr); |
| 2148 Push(AddInstruction(new HPushArgument(Pop()))); | 2152 Push(AddInstruction(new(zone()) HPushArgument(Pop()))); |
| 2149 } | 2153 } |
| 2150 | 2154 |
| 2151 | 2155 |
| 2152 void HGraphBuilder::VisitArgumentList(ZoneList<Expression*>* arguments) { | 2156 void HGraphBuilder::VisitArgumentList(ZoneList<Expression*>* arguments) { |
| 2153 for (int i = 0; i < arguments->length(); i++) { | 2157 for (int i = 0; i < arguments->length(); i++) { |
| 2154 VisitArgument(arguments->at(i)); | 2158 VisitArgument(arguments->at(i)); |
| 2155 if (HasStackOverflow() || current_block() == NULL) return; | 2159 if (HasStackOverflow() || current_block() == NULL) return; |
| 2156 } | 2160 } |
| 2157 } | 2161 } |
| 2158 | 2162 |
| 2159 | 2163 |
| 2160 void HGraphBuilder::VisitExpressions(ZoneList<Expression*>* exprs) { | 2164 void HGraphBuilder::VisitExpressions(ZoneList<Expression*>* exprs) { |
| 2161 for (int i = 0; i < exprs->length(); ++i) { | 2165 for (int i = 0; i < exprs->length(); ++i) { |
| 2162 VISIT_FOR_VALUE(exprs->at(i)); | 2166 VISIT_FOR_VALUE(exprs->at(i)); |
| 2163 } | 2167 } |
| 2164 } | 2168 } |
| 2165 | 2169 |
| 2166 | 2170 |
| 2167 HGraph* HGraphBuilder::CreateGraph() { | 2171 HGraph* HGraphBuilder::CreateGraph() { |
| 2168 graph_ = new HGraph(info()); | 2172 graph_ = new(zone()) HGraph(info()); |
| 2169 if (FLAG_hydrogen_stats) HStatistics::Instance()->Initialize(info()); | 2173 if (FLAG_hydrogen_stats) HStatistics::Instance()->Initialize(info()); |
| 2170 | 2174 |
| 2171 { | 2175 { |
| 2172 HPhase phase("Block building"); | 2176 HPhase phase("Block building"); |
| 2173 current_block_ = graph()->entry_block(); | 2177 current_block_ = graph()->entry_block(); |
| 2174 | 2178 |
| 2175 Scope* scope = info()->scope(); | 2179 Scope* scope = info()->scope(); |
| 2176 if (scope->HasIllegalRedeclaration()) { | 2180 if (scope->HasIllegalRedeclaration()) { |
| 2177 Bailout("function with illegal redeclaration"); | 2181 Bailout("function with illegal redeclaration"); |
| 2178 return NULL; | 2182 return NULL; |
| 2179 } | 2183 } |
| 2180 SetupScope(scope); | 2184 SetupScope(scope); |
| 2181 VisitDeclarations(scope->declarations()); | 2185 VisitDeclarations(scope->declarations()); |
| 2182 AddInstruction(new HStackCheck()); | 2186 AddInstruction(new(zone()) HStackCheck()); |
| 2183 | 2187 |
| 2184 // Add an edge to the body entry. This is warty: the graph's start | 2188 // Add an edge to the body entry. This is warty: the graph's start |
| 2185 // environment will be used by the Lithium translation as the initial | 2189 // environment will be used by the Lithium translation as the initial |
| 2186 // environment on graph entry, but it has now been mutated by the | 2190 // environment on graph entry, but it has now been mutated by the |
| 2187 // Hydrogen translation of the instructions in the start block. This | 2191 // Hydrogen translation of the instructions in the start block. This |
| 2188 // environment uses values which have not been defined yet. These | 2192 // environment uses values which have not been defined yet. These |
| 2189 // Hydrogen instructions will then be replayed by the Lithium | 2193 // Hydrogen instructions will then be replayed by the Lithium |
| 2190 // translation, so they cannot have an environment effect. The edge to | 2194 // translation, so they cannot have an environment effect. The edge to |
| 2191 // the body's entry block (along with some special logic for the start | 2195 // the body's entry block (along with some special logic for the start |
| 2192 // block in HInstruction::InsertAfter) seals the start block from | 2196 // block in HInstruction::InsertAfter) seals the start block from |
| 2193 // getting unwanted instructions inserted. | 2197 // getting unwanted instructions inserted. |
| 2194 // | 2198 // |
| 2195 // TODO(kmillikin): Fix this. Stop mutating the initial environment. | 2199 // TODO(kmillikin): Fix this. Stop mutating the initial environment. |
| 2196 // Make the Hydrogen instructions in the initial block into Hydrogen | 2200 // Make the Hydrogen instructions in the initial block into Hydrogen |
| 2197 // values (but not instructions), present in the initial environment and | 2201 // values (but not instructions), present in the initial environment and |
| 2198 // not replayed by the Lithium translation. | 2202 // not replayed by the Lithium translation. |
| 2199 HEnvironment* initial_env = environment()->CopyWithoutHistory(); | 2203 HEnvironment* initial_env = environment()->CopyWithoutHistory(); |
| 2200 HBasicBlock* body_entry = CreateBasicBlock(initial_env); | 2204 HBasicBlock* body_entry = CreateBasicBlock(initial_env); |
| 2201 current_block()->Goto(body_entry); | 2205 current_block()->Goto(body_entry); |
| 2202 body_entry->SetJoinId(info()->function()->id()); | 2206 body_entry->SetJoinId(info()->function()->id()); |
| 2203 set_current_block(body_entry); | 2207 set_current_block(body_entry); |
| 2204 VisitStatements(info()->function()->body()); | 2208 VisitStatements(info()->function()->body()); |
| 2205 if (HasStackOverflow()) return NULL; | 2209 if (HasStackOverflow()) return NULL; |
| 2206 | 2210 |
| 2207 if (current_block() != NULL) { | 2211 if (current_block() != NULL) { |
| 2208 HReturn* instr = new HReturn(graph()->GetConstantUndefined()); | 2212 HReturn* instr = new(zone()) HReturn(graph()->GetConstantUndefined()); |
| 2209 current_block()->FinishExit(instr); | 2213 current_block()->FinishExit(instr); |
| 2210 set_current_block(NULL); | 2214 set_current_block(NULL); |
| 2211 } | 2215 } |
| 2212 } | 2216 } |
| 2213 | 2217 |
| 2214 graph()->OrderBlocks(); | 2218 graph()->OrderBlocks(); |
| 2215 graph()->AssignDominators(); | 2219 graph()->AssignDominators(); |
| 2216 graph()->EliminateRedundantPhis(); | 2220 graph()->EliminateRedundantPhis(); |
| 2217 if (FLAG_eliminate_dead_phis) graph()->EliminateUnreachablePhis(); | 2221 if (FLAG_eliminate_dead_phis) graph()->EliminateUnreachablePhis(); |
| 2218 if (!graph()->CollectPhis()) { | 2222 if (!graph()->CollectPhis()) { |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2275 | 2279 |
| 2276 template <int V> | 2280 template <int V> |
| 2277 HInstruction* HGraphBuilder::PreProcessCall(HCall<V>* call) { | 2281 HInstruction* HGraphBuilder::PreProcessCall(HCall<V>* call) { |
| 2278 int count = call->argument_count(); | 2282 int count = call->argument_count(); |
| 2279 ZoneList<HValue*> arguments(count); | 2283 ZoneList<HValue*> arguments(count); |
| 2280 for (int i = 0; i < count; ++i) { | 2284 for (int i = 0; i < count; ++i) { |
| 2281 arguments.Add(Pop()); | 2285 arguments.Add(Pop()); |
| 2282 } | 2286 } |
| 2283 | 2287 |
| 2284 while (!arguments.is_empty()) { | 2288 while (!arguments.is_empty()) { |
| 2285 AddInstruction(new HPushArgument(arguments.RemoveLast())); | 2289 AddInstruction(new(zone()) HPushArgument(arguments.RemoveLast())); |
| 2286 } | 2290 } |
| 2287 return call; | 2291 return call; |
| 2288 } | 2292 } |
| 2289 | 2293 |
| 2290 | 2294 |
| 2291 void HGraphBuilder::SetupScope(Scope* scope) { | 2295 void HGraphBuilder::SetupScope(Scope* scope) { |
| 2292 // We don't yet handle the function name for named function expressions. | 2296 // We don't yet handle the function name for named function expressions. |
| 2293 if (scope->function() != NULL) BAILOUT("named function expression"); | 2297 if (scope->function() != NULL) BAILOUT("named function expression"); |
| 2294 | 2298 |
| 2295 HConstant* undefined_constant = new HConstant( | 2299 HConstant* undefined_constant = new(zone()) HConstant( |
| 2296 isolate()->factory()->undefined_value(), Representation::Tagged()); | 2300 isolate()->factory()->undefined_value(), Representation::Tagged()); |
| 2297 AddInstruction(undefined_constant); | 2301 AddInstruction(undefined_constant); |
| 2298 graph_->set_undefined_constant(undefined_constant); | 2302 graph_->set_undefined_constant(undefined_constant); |
| 2299 | 2303 |
| 2300 // Set the initial values of parameters including "this". "This" has | 2304 // Set the initial values of parameters including "this". "This" has |
| 2301 // parameter index 0. | 2305 // parameter index 0. |
| 2302 int count = scope->num_parameters() + 1; | 2306 int count = scope->num_parameters() + 1; |
| 2303 for (int i = 0; i < count; ++i) { | 2307 for (int i = 0; i < count; ++i) { |
| 2304 HInstruction* parameter = AddInstruction(new HParameter(i)); | 2308 HInstruction* parameter = AddInstruction(new(zone()) HParameter(i)); |
| 2305 environment()->Bind(i, parameter); | 2309 environment()->Bind(i, parameter); |
| 2306 } | 2310 } |
| 2307 | 2311 |
| 2308 // Set the initial values of stack-allocated locals. | 2312 // Set the initial values of stack-allocated locals. |
| 2309 for (int i = count; i < environment()->length(); ++i) { | 2313 for (int i = count; i < environment()->length(); ++i) { |
| 2310 environment()->Bind(i, undefined_constant); | 2314 environment()->Bind(i, undefined_constant); |
| 2311 } | 2315 } |
| 2312 | 2316 |
| 2313 // Handle the arguments and arguments shadow variables specially (they do | 2317 // Handle the arguments and arguments shadow variables specially (they do |
| 2314 // not have declarations). | 2318 // not have declarations). |
| 2315 if (scope->arguments() != NULL) { | 2319 if (scope->arguments() != NULL) { |
| 2316 if (!scope->arguments()->IsStackAllocated() || | 2320 if (!scope->arguments()->IsStackAllocated() || |
| 2317 (scope->arguments_shadow() != NULL && | 2321 (scope->arguments_shadow() != NULL && |
| 2318 !scope->arguments_shadow()->IsStackAllocated())) { | 2322 !scope->arguments_shadow()->IsStackAllocated())) { |
| 2319 BAILOUT("context-allocated arguments"); | 2323 BAILOUT("context-allocated arguments"); |
| 2320 } | 2324 } |
| 2321 HArgumentsObject* object = new HArgumentsObject; | 2325 HArgumentsObject* object = new(zone()) HArgumentsObject; |
| 2322 AddInstruction(object); | 2326 AddInstruction(object); |
| 2323 graph()->SetArgumentsObject(object); | 2327 graph()->SetArgumentsObject(object); |
| 2324 environment()->Bind(scope->arguments(), object); | 2328 environment()->Bind(scope->arguments(), object); |
| 2325 if (scope->arguments_shadow() != NULL) { | 2329 if (scope->arguments_shadow() != NULL) { |
| 2326 environment()->Bind(scope->arguments_shadow(), object); | 2330 environment()->Bind(scope->arguments_shadow(), object); |
| 2327 } | 2331 } |
| 2328 } | 2332 } |
| 2329 } | 2333 } |
| 2330 | 2334 |
| 2331 | 2335 |
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2450 set_current_block(NULL); | 2454 set_current_block(NULL); |
| 2451 } | 2455 } |
| 2452 | 2456 |
| 2453 | 2457 |
| 2454 void HGraphBuilder::VisitReturnStatement(ReturnStatement* stmt) { | 2458 void HGraphBuilder::VisitReturnStatement(ReturnStatement* stmt) { |
| 2455 AstContext* context = call_context(); | 2459 AstContext* context = call_context(); |
| 2456 if (context == NULL) { | 2460 if (context == NULL) { |
| 2457 // Not an inlined return, so an actual one. | 2461 // Not an inlined return, so an actual one. |
| 2458 VISIT_FOR_VALUE(stmt->expression()); | 2462 VISIT_FOR_VALUE(stmt->expression()); |
| 2459 HValue* result = environment()->Pop(); | 2463 HValue* result = environment()->Pop(); |
| 2460 current_block()->FinishExit(new HReturn(result)); | 2464 current_block()->FinishExit(new(zone()) HReturn(result)); |
| 2461 set_current_block(NULL); | 2465 set_current_block(NULL); |
| 2462 } else { | 2466 } else { |
| 2463 // Return from an inlined function, visit the subexpression in the | 2467 // Return from an inlined function, visit the subexpression in the |
| 2464 // expression context of the call. | 2468 // expression context of the call. |
| 2465 if (context->IsTest()) { | 2469 if (context->IsTest()) { |
| 2466 TestContext* test = TestContext::cast(context); | 2470 TestContext* test = TestContext::cast(context); |
| 2467 VisitForControl(stmt->expression(), | 2471 VisitForControl(stmt->expression(), |
| 2468 test->if_true(), | 2472 test->if_true(), |
| 2469 test->if_false()); | 2473 test->if_false()); |
| 2470 } else if (context->IsEffect()) { | 2474 } else if (context->IsEffect()) { |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2519 clause->RecordTypeFeedback(oracle()); | 2523 clause->RecordTypeFeedback(oracle()); |
| 2520 if (!clause->IsSmiCompare()) { | 2524 if (!clause->IsSmiCompare()) { |
| 2521 current_block()->FinishExitWithDeoptimization(); | 2525 current_block()->FinishExitWithDeoptimization(); |
| 2522 set_current_block(NULL); | 2526 set_current_block(NULL); |
| 2523 break; | 2527 break; |
| 2524 } | 2528 } |
| 2525 | 2529 |
| 2526 // Otherwise generate a compare and branch. | 2530 // Otherwise generate a compare and branch. |
| 2527 VISIT_FOR_VALUE(clause->label()); | 2531 VISIT_FOR_VALUE(clause->label()); |
| 2528 HValue* label_value = Pop(); | 2532 HValue* label_value = Pop(); |
| 2529 HCompare* compare = new HCompare(tag_value, label_value, Token::EQ_STRICT); | 2533 HCompare* compare = |
| 2534 new(zone()) HCompare(tag_value, label_value, Token::EQ_STRICT); |
| 2530 compare->SetInputRepresentation(Representation::Integer32()); | 2535 compare->SetInputRepresentation(Representation::Integer32()); |
| 2531 ASSERT(!compare->HasSideEffects()); | 2536 ASSERT(!compare->HasSideEffects()); |
| 2532 AddInstruction(compare); | 2537 AddInstruction(compare); |
| 2533 HBasicBlock* body_block = graph()->CreateBasicBlock(); | 2538 HBasicBlock* body_block = graph()->CreateBasicBlock(); |
| 2534 HBasicBlock* next_test_block = graph()->CreateBasicBlock(); | 2539 HBasicBlock* next_test_block = graph()->CreateBasicBlock(); |
| 2535 HTest* branch = new HTest(compare, body_block, next_test_block); | 2540 HTest* branch = new(zone()) HTest(compare, body_block, next_test_block); |
| 2536 current_block()->Finish(branch); | 2541 current_block()->Finish(branch); |
| 2537 set_current_block(next_test_block); | 2542 set_current_block(next_test_block); |
| 2538 } | 2543 } |
| 2539 | 2544 |
| 2540 // Save the current block to use for the default or to join with the | 2545 // Save the current block to use for the default or to join with the |
| 2541 // exit. This block is NULL if we deoptimized. | 2546 // exit. This block is NULL if we deoptimized. |
| 2542 HBasicBlock* last_block = current_block(); | 2547 HBasicBlock* last_block = current_block(); |
| 2543 | 2548 |
| 2544 // 2. Loop over the clauses and the linked list of tests in lockstep, | 2549 // 2. Loop over the clauses and the linked list of tests in lockstep, |
| 2545 // translating the clause bodies. | 2550 // translating the clause bodies. |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2611 return statement->OsrEntryId() == info()->osr_ast_id(); | 2616 return statement->OsrEntryId() == info()->osr_ast_id(); |
| 2612 } | 2617 } |
| 2613 | 2618 |
| 2614 | 2619 |
| 2615 void HGraphBuilder::PreProcessOsrEntry(IterationStatement* statement) { | 2620 void HGraphBuilder::PreProcessOsrEntry(IterationStatement* statement) { |
| 2616 if (!HasOsrEntryAt(statement)) return; | 2621 if (!HasOsrEntryAt(statement)) return; |
| 2617 | 2622 |
| 2618 HBasicBlock* non_osr_entry = graph()->CreateBasicBlock(); | 2623 HBasicBlock* non_osr_entry = graph()->CreateBasicBlock(); |
| 2619 HBasicBlock* osr_entry = graph()->CreateBasicBlock(); | 2624 HBasicBlock* osr_entry = graph()->CreateBasicBlock(); |
| 2620 HValue* true_value = graph()->GetConstantTrue(); | 2625 HValue* true_value = graph()->GetConstantTrue(); |
| 2621 HTest* test = new HTest(true_value, non_osr_entry, osr_entry); | 2626 HTest* test = new(zone()) HTest(true_value, non_osr_entry, osr_entry); |
| 2622 current_block()->Finish(test); | 2627 current_block()->Finish(test); |
| 2623 | 2628 |
| 2624 HBasicBlock* loop_predecessor = graph()->CreateBasicBlock(); | 2629 HBasicBlock* loop_predecessor = graph()->CreateBasicBlock(); |
| 2625 non_osr_entry->Goto(loop_predecessor); | 2630 non_osr_entry->Goto(loop_predecessor); |
| 2626 | 2631 |
| 2627 set_current_block(osr_entry); | 2632 set_current_block(osr_entry); |
| 2628 int osr_entry_id = statement->OsrEntryId(); | 2633 int osr_entry_id = statement->OsrEntryId(); |
| 2629 // We want the correct environment at the OsrEntry instruction. Build | 2634 // We want the correct environment at the OsrEntry instruction. Build |
| 2630 // it explicitly. The expression stack should be empty. | 2635 // it explicitly. The expression stack should be empty. |
| 2631 int count = environment()->length(); | 2636 int count = environment()->length(); |
| 2632 ASSERT(count == | 2637 ASSERT(count == |
| 2633 (environment()->parameter_count() + environment()->local_count())); | 2638 (environment()->parameter_count() + environment()->local_count())); |
| 2634 for (int i = 0; i < count; ++i) { | 2639 for (int i = 0; i < count; ++i) { |
| 2635 HUnknownOSRValue* unknown = new HUnknownOSRValue; | 2640 HUnknownOSRValue* unknown = new(zone()) HUnknownOSRValue; |
| 2636 AddInstruction(unknown); | 2641 AddInstruction(unknown); |
| 2637 environment()->Bind(i, unknown); | 2642 environment()->Bind(i, unknown); |
| 2638 } | 2643 } |
| 2639 | 2644 |
| 2640 AddSimulate(osr_entry_id); | 2645 AddSimulate(osr_entry_id); |
| 2641 AddInstruction(new HOsrEntry(osr_entry_id)); | 2646 AddInstruction(new(zone()) HOsrEntry(osr_entry_id)); |
| 2642 current_block()->Goto(loop_predecessor); | 2647 current_block()->Goto(loop_predecessor); |
| 2643 loop_predecessor->SetJoinId(statement->EntryId()); | 2648 loop_predecessor->SetJoinId(statement->EntryId()); |
| 2644 set_current_block(loop_predecessor); | 2649 set_current_block(loop_predecessor); |
| 2645 } | 2650 } |
| 2646 | 2651 |
| 2647 | 2652 |
| 2648 void HGraphBuilder::VisitDoWhileStatement(DoWhileStatement* stmt) { | 2653 void HGraphBuilder::VisitDoWhileStatement(DoWhileStatement* stmt) { |
| 2649 ASSERT(current_block() != NULL); | 2654 ASSERT(current_block() != NULL); |
| 2650 PreProcessOsrEntry(stmt); | 2655 PreProcessOsrEntry(stmt); |
| 2651 HBasicBlock* loop_entry = CreateLoopHeaderBlock(); | 2656 HBasicBlock* loop_entry = CreateLoopHeaderBlock(); |
| (...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2800 | 2805 |
| 2801 void HGraphBuilder::VisitFunctionLiteral(FunctionLiteral* expr) { | 2806 void HGraphBuilder::VisitFunctionLiteral(FunctionLiteral* expr) { |
| 2802 Handle<SharedFunctionInfo> shared_info = | 2807 Handle<SharedFunctionInfo> shared_info = |
| 2803 SearchSharedFunctionInfo(info()->shared_info()->code(), | 2808 SearchSharedFunctionInfo(info()->shared_info()->code(), |
| 2804 expr); | 2809 expr); |
| 2805 if (shared_info.is_null()) { | 2810 if (shared_info.is_null()) { |
| 2806 shared_info = Compiler::BuildFunctionInfo(expr, info()->script()); | 2811 shared_info = Compiler::BuildFunctionInfo(expr, info()->script()); |
| 2807 } | 2812 } |
| 2808 CHECK_BAILOUT; | 2813 CHECK_BAILOUT; |
| 2809 HFunctionLiteral* instr = | 2814 HFunctionLiteral* instr = |
| 2810 new HFunctionLiteral(shared_info, expr->pretenure()); | 2815 new(zone()) HFunctionLiteral(shared_info, expr->pretenure()); |
| 2811 ast_context()->ReturnInstruction(instr, expr->id()); | 2816 ast_context()->ReturnInstruction(instr, expr->id()); |
| 2812 } | 2817 } |
| 2813 | 2818 |
| 2814 | 2819 |
| 2815 void HGraphBuilder::VisitSharedFunctionInfoLiteral( | 2820 void HGraphBuilder::VisitSharedFunctionInfoLiteral( |
| 2816 SharedFunctionInfoLiteral* expr) { | 2821 SharedFunctionInfoLiteral* expr) { |
| 2817 BAILOUT("SharedFunctionInfoLiteral"); | 2822 BAILOUT("SharedFunctionInfoLiteral"); |
| 2818 } | 2823 } |
| 2819 | 2824 |
| 2820 | 2825 |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2857 lookup->holder() != *global) { | 2862 lookup->holder() != *global) { |
| 2858 return kUseGeneric; | 2863 return kUseGeneric; |
| 2859 } | 2864 } |
| 2860 | 2865 |
| 2861 return kUseCell; | 2866 return kUseCell; |
| 2862 } | 2867 } |
| 2863 | 2868 |
| 2864 | 2869 |
| 2865 HValue* HGraphBuilder::BuildContextChainWalk(Variable* var) { | 2870 HValue* HGraphBuilder::BuildContextChainWalk(Variable* var) { |
| 2866 ASSERT(var->IsContextSlot()); | 2871 ASSERT(var->IsContextSlot()); |
| 2867 HInstruction* context = new HContext; | 2872 HInstruction* context = new(zone()) HContext; |
| 2868 AddInstruction(context); | 2873 AddInstruction(context); |
| 2869 int length = info()->scope()->ContextChainLength(var->scope()); | 2874 int length = info()->scope()->ContextChainLength(var->scope()); |
| 2870 while (length-- > 0) { | 2875 while (length-- > 0) { |
| 2871 context = new HOuterContext(context); | 2876 context = new(zone()) HOuterContext(context); |
| 2872 AddInstruction(context); | 2877 AddInstruction(context); |
| 2873 } | 2878 } |
| 2874 return context; | 2879 return context; |
| 2875 } | 2880 } |
| 2876 | 2881 |
| 2877 | 2882 |
| 2878 void HGraphBuilder::VisitVariableProxy(VariableProxy* expr) { | 2883 void HGraphBuilder::VisitVariableProxy(VariableProxy* expr) { |
| 2879 Variable* variable = expr->AsVariable(); | 2884 Variable* variable = expr->AsVariable(); |
| 2880 if (variable == NULL) { | 2885 if (variable == NULL) { |
| 2881 BAILOUT("reference to rewritten variable"); | 2886 BAILOUT("reference to rewritten variable"); |
| 2882 } else if (variable->IsStackAllocated()) { | 2887 } else if (variable->IsStackAllocated()) { |
| 2883 if (environment()->Lookup(variable)->CheckFlag(HValue::kIsArguments)) { | 2888 if (environment()->Lookup(variable)->CheckFlag(HValue::kIsArguments)) { |
| 2884 BAILOUT("unsupported context for arguments object"); | 2889 BAILOUT("unsupported context for arguments object"); |
| 2885 } | 2890 } |
| 2886 ast_context()->ReturnValue(environment()->Lookup(variable)); | 2891 ast_context()->ReturnValue(environment()->Lookup(variable)); |
| 2887 } else if (variable->IsContextSlot()) { | 2892 } else if (variable->IsContextSlot()) { |
| 2888 if (variable->mode() == Variable::CONST) { | 2893 if (variable->mode() == Variable::CONST) { |
| 2889 BAILOUT("reference to const context slot"); | 2894 BAILOUT("reference to const context slot"); |
| 2890 } | 2895 } |
| 2891 HValue* context = BuildContextChainWalk(variable); | 2896 HValue* context = BuildContextChainWalk(variable); |
| 2892 int index = variable->AsSlot()->index(); | 2897 int index = variable->AsSlot()->index(); |
| 2893 HLoadContextSlot* instr = new HLoadContextSlot(context, index); | 2898 HLoadContextSlot* instr = new(zone()) HLoadContextSlot(context, index); |
| 2894 ast_context()->ReturnInstruction(instr, expr->id()); | 2899 ast_context()->ReturnInstruction(instr, expr->id()); |
| 2895 } else if (variable->is_global()) { | 2900 } else if (variable->is_global()) { |
| 2896 LookupResult lookup; | 2901 LookupResult lookup; |
| 2897 GlobalPropertyAccess type = LookupGlobalProperty(variable, &lookup, false); | 2902 GlobalPropertyAccess type = LookupGlobalProperty(variable, &lookup, false); |
| 2898 | 2903 |
| 2899 if (type == kUseCell && | 2904 if (type == kUseCell && |
| 2900 info()->global_object()->IsAccessCheckNeeded()) { | 2905 info()->global_object()->IsAccessCheckNeeded()) { |
| 2901 type = kUseGeneric; | 2906 type = kUseGeneric; |
| 2902 } | 2907 } |
| 2903 | 2908 |
| 2904 if (type == kUseCell) { | 2909 if (type == kUseCell) { |
| 2905 Handle<GlobalObject> global(info()->global_object()); | 2910 Handle<GlobalObject> global(info()->global_object()); |
| 2906 Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(&lookup)); | 2911 Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(&lookup)); |
| 2907 bool check_hole = !lookup.IsDontDelete() || lookup.IsReadOnly(); | 2912 bool check_hole = !lookup.IsDontDelete() || lookup.IsReadOnly(); |
| 2908 HLoadGlobalCell* instr = new HLoadGlobalCell(cell, check_hole); | 2913 HLoadGlobalCell* instr = new(zone()) HLoadGlobalCell(cell, check_hole); |
| 2909 ast_context()->ReturnInstruction(instr, expr->id()); | 2914 ast_context()->ReturnInstruction(instr, expr->id()); |
| 2910 } else { | 2915 } else { |
| 2911 HContext* context = new HContext; | 2916 HContext* context = new(zone()) HContext; |
| 2912 AddInstruction(context); | 2917 AddInstruction(context); |
| 2913 HGlobalObject* global_object = new HGlobalObject(context); | 2918 HGlobalObject* global_object = new(zone()) HGlobalObject(context); |
| 2914 AddInstruction(global_object); | 2919 AddInstruction(global_object); |
| 2915 HLoadGlobalGeneric* instr = | 2920 HLoadGlobalGeneric* instr = |
| 2916 new HLoadGlobalGeneric(context, | 2921 new(zone()) HLoadGlobalGeneric(context, |
| 2917 global_object, | 2922 global_object, |
| 2918 variable->name(), | 2923 variable->name(), |
| 2919 ast_context()->is_for_typeof()); | 2924 ast_context()->is_for_typeof()); |
| 2920 instr->set_position(expr->position()); | 2925 instr->set_position(expr->position()); |
| 2921 ASSERT(instr->HasSideEffects()); | 2926 ASSERT(instr->HasSideEffects()); |
| 2922 ast_context()->ReturnInstruction(instr, expr->id()); | 2927 ast_context()->ReturnInstruction(instr, expr->id()); |
| 2923 } | 2928 } |
| 2924 } else { | 2929 } else { |
| 2925 BAILOUT("reference to a variable which requires dynamic lookup"); | 2930 BAILOUT("reference to a variable which requires dynamic lookup"); |
| 2926 } | 2931 } |
| 2927 } | 2932 } |
| 2928 | 2933 |
| 2929 | 2934 |
| 2930 void HGraphBuilder::VisitLiteral(Literal* expr) { | 2935 void HGraphBuilder::VisitLiteral(Literal* expr) { |
| 2931 HConstant* instr = new HConstant(expr->handle(), Representation::Tagged()); | 2936 HConstant* instr = |
| 2937 new(zone()) HConstant(expr->handle(), Representation::Tagged()); |
| 2932 ast_context()->ReturnInstruction(instr, expr->id()); | 2938 ast_context()->ReturnInstruction(instr, expr->id()); |
| 2933 } | 2939 } |
| 2934 | 2940 |
| 2935 | 2941 |
| 2936 void HGraphBuilder::VisitRegExpLiteral(RegExpLiteral* expr) { | 2942 void HGraphBuilder::VisitRegExpLiteral(RegExpLiteral* expr) { |
| 2937 HRegExpLiteral* instr = new HRegExpLiteral(expr->pattern(), | 2943 HRegExpLiteral* instr = new(zone()) HRegExpLiteral(expr->pattern(), |
| 2938 expr->flags(), | 2944 expr->flags(), |
| 2939 expr->literal_index()); | 2945 expr->literal_index()); |
| 2940 ast_context()->ReturnInstruction(instr, expr->id()); | 2946 ast_context()->ReturnInstruction(instr, expr->id()); |
| 2941 } | 2947 } |
| 2942 | 2948 |
| 2943 | 2949 |
| 2944 void HGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) { | 2950 void HGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) { |
| 2945 HContext* context = new HContext; | 2951 HContext* context = new(zone()) HContext; |
| 2946 AddInstruction(context); | 2952 AddInstruction(context); |
| 2947 HObjectLiteral* literal = (new HObjectLiteral(context, | 2953 HObjectLiteral* literal = |
| 2948 expr->constant_properties(), | 2954 new(zone()) HObjectLiteral(context, |
| 2949 expr->fast_elements(), | 2955 expr->constant_properties(), |
| 2950 expr->literal_index(), | 2956 expr->fast_elements(), |
| 2951 expr->depth(), | 2957 expr->literal_index(), |
| 2952 expr->has_function())); | 2958 expr->depth(), |
| 2959 expr->has_function()); |
| 2953 // The object is expected in the bailout environment during computation | 2960 // The object is expected in the bailout environment during computation |
| 2954 // of the property values and is the value of the entire expression. | 2961 // of the property values and is the value of the entire expression. |
| 2955 PushAndAdd(literal); | 2962 PushAndAdd(literal); |
| 2956 | 2963 |
| 2957 expr->CalculateEmitStore(); | 2964 expr->CalculateEmitStore(); |
| 2958 | 2965 |
| 2959 for (int i = 0; i < expr->properties()->length(); i++) { | 2966 for (int i = 0; i < expr->properties()->length(); i++) { |
| 2960 ObjectLiteral::Property* property = expr->properties()->at(i); | 2967 ObjectLiteral::Property* property = expr->properties()->at(i); |
| 2961 if (property->IsCompileTimeValue()) continue; | 2968 if (property->IsCompileTimeValue()) continue; |
| 2962 | 2969 |
| 2963 Literal* key = property->key(); | 2970 Literal* key = property->key(); |
| 2964 Expression* value = property->value(); | 2971 Expression* value = property->value(); |
| 2965 | 2972 |
| 2966 switch (property->kind()) { | 2973 switch (property->kind()) { |
| 2967 case ObjectLiteral::Property::MATERIALIZED_LITERAL: | 2974 case ObjectLiteral::Property::MATERIALIZED_LITERAL: |
| 2968 ASSERT(!CompileTimeValue::IsCompileTimeValue(value)); | 2975 ASSERT(!CompileTimeValue::IsCompileTimeValue(value)); |
| 2969 // Fall through. | 2976 // Fall through. |
| 2970 case ObjectLiteral::Property::COMPUTED: | 2977 case ObjectLiteral::Property::COMPUTED: |
| 2971 if (key->handle()->IsSymbol()) { | 2978 if (key->handle()->IsSymbol()) { |
| 2972 if (property->emit_store()) { | 2979 if (property->emit_store()) { |
| 2973 VISIT_FOR_VALUE(value); | 2980 VISIT_FOR_VALUE(value); |
| 2974 HValue* value = Pop(); | 2981 HValue* value = Pop(); |
| 2975 Handle<String> name = Handle<String>::cast(key->handle()); | 2982 Handle<String> name = Handle<String>::cast(key->handle()); |
| 2976 HStoreNamedGeneric* store = | 2983 HStoreNamedGeneric* store = |
| 2977 new HStoreNamedGeneric(context, literal, name, value); | 2984 new(zone()) HStoreNamedGeneric(context, literal, name, value); |
| 2978 AddInstruction(store); | 2985 AddInstruction(store); |
| 2979 AddSimulate(key->id()); | 2986 AddSimulate(key->id()); |
| 2980 } else { | 2987 } else { |
| 2981 VISIT_FOR_EFFECT(value); | 2988 VISIT_FOR_EFFECT(value); |
| 2982 } | 2989 } |
| 2983 break; | 2990 break; |
| 2984 } | 2991 } |
| 2985 // Fall through. | 2992 // Fall through. |
| 2986 case ObjectLiteral::Property::PROTOTYPE: | 2993 case ObjectLiteral::Property::PROTOTYPE: |
| 2987 case ObjectLiteral::Property::SETTER: | 2994 case ObjectLiteral::Property::SETTER: |
| 2988 case ObjectLiteral::Property::GETTER: | 2995 case ObjectLiteral::Property::GETTER: |
| 2989 BAILOUT("Object literal with complex property"); | 2996 BAILOUT("Object literal with complex property"); |
| 2990 default: UNREACHABLE(); | 2997 default: UNREACHABLE(); |
| 2991 } | 2998 } |
| 2992 } | 2999 } |
| 2993 | 3000 |
| 2994 if (expr->has_function()) { | 3001 if (expr->has_function()) { |
| 2995 // Return the result of the transformation to fast properties | 3002 // Return the result of the transformation to fast properties |
| 2996 // instead of the original since this operation changes the map | 3003 // instead of the original since this operation changes the map |
| 2997 // of the object. This makes sure that the original object won't | 3004 // of the object. This makes sure that the original object won't |
| 2998 // be used by other optimized code before it is transformed | 3005 // be used by other optimized code before it is transformed |
| 2999 // (e.g. because of code motion). | 3006 // (e.g. because of code motion). |
| 3000 HToFastProperties* result = new HToFastProperties(Pop()); | 3007 HToFastProperties* result = new(zone()) HToFastProperties(Pop()); |
| 3001 AddInstruction(result); | 3008 AddInstruction(result); |
| 3002 ast_context()->ReturnValue(result); | 3009 ast_context()->ReturnValue(result); |
| 3003 } else { | 3010 } else { |
| 3004 ast_context()->ReturnValue(Pop()); | 3011 ast_context()->ReturnValue(Pop()); |
| 3005 } | 3012 } |
| 3006 } | 3013 } |
| 3007 | 3014 |
| 3008 | 3015 |
| 3009 void HGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) { | 3016 void HGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) { |
| 3010 ZoneList<Expression*>* subexprs = expr->values(); | 3017 ZoneList<Expression*>* subexprs = expr->values(); |
| 3011 int length = subexprs->length(); | 3018 int length = subexprs->length(); |
| 3012 | 3019 |
| 3013 HArrayLiteral* literal = new HArrayLiteral(expr->constant_elements(), | 3020 HArrayLiteral* literal = new(zone()) HArrayLiteral(expr->constant_elements(), |
| 3014 length, | 3021 length, |
| 3015 expr->literal_index(), | 3022 expr->literal_index(), |
| 3016 expr->depth()); | 3023 expr->depth()); |
| 3017 // The array is expected in the bailout environment during computation | 3024 // The array is expected in the bailout environment during computation |
| 3018 // of the property values and is the value of the entire expression. | 3025 // of the property values and is the value of the entire expression. |
| 3019 PushAndAdd(literal); | 3026 PushAndAdd(literal); |
| 3020 | 3027 |
| 3021 HLoadElements* elements = NULL; | 3028 HLoadElements* elements = NULL; |
| 3022 | 3029 |
| 3023 for (int i = 0; i < length; i++) { | 3030 for (int i = 0; i < length; i++) { |
| 3024 Expression* subexpr = subexprs->at(i); | 3031 Expression* subexpr = subexprs->at(i); |
| 3025 // If the subexpression is a literal or a simple materialized literal it | 3032 // If the subexpression is a literal or a simple materialized literal it |
| 3026 // is already set in the cloned array. | 3033 // is already set in the cloned array. |
| 3027 if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue; | 3034 if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue; |
| 3028 | 3035 |
| 3029 VISIT_FOR_VALUE(subexpr); | 3036 VISIT_FOR_VALUE(subexpr); |
| 3030 HValue* value = Pop(); | 3037 HValue* value = Pop(); |
| 3031 if (!Smi::IsValid(i)) BAILOUT("Non-smi key in array literal"); | 3038 if (!Smi::IsValid(i)) BAILOUT("Non-smi key in array literal"); |
| 3032 | 3039 |
| 3033 // Load the elements array before the first store. | 3040 // Load the elements array before the first store. |
| 3034 if (elements == NULL) { | 3041 if (elements == NULL) { |
| 3035 elements = new HLoadElements(literal); | 3042 elements = new(zone()) HLoadElements(literal); |
| 3036 AddInstruction(elements); | 3043 AddInstruction(elements); |
| 3037 } | 3044 } |
| 3038 | 3045 |
| 3039 HValue* key = AddInstruction(new HConstant(Handle<Object>(Smi::FromInt(i)), | 3046 HValue* key = AddInstruction( |
| 3040 Representation::Integer32())); | 3047 new(zone()) HConstant(Handle<Object>(Smi::FromInt(i)), |
| 3041 AddInstruction(new HStoreKeyedFastElement(elements, key, value)); | 3048 Representation::Integer32())); |
| 3049 AddInstruction(new(zone()) HStoreKeyedFastElement(elements, key, value)); |
| 3042 AddSimulate(expr->GetIdForElement(i)); | 3050 AddSimulate(expr->GetIdForElement(i)); |
| 3043 } | 3051 } |
| 3044 ast_context()->ReturnValue(Pop()); | 3052 ast_context()->ReturnValue(Pop()); |
| 3045 } | 3053 } |
| 3046 | 3054 |
| 3047 | 3055 |
| 3048 void HGraphBuilder::VisitCatchExtensionObject(CatchExtensionObject* expr) { | 3056 void HGraphBuilder::VisitCatchExtensionObject(CatchExtensionObject* expr) { |
| 3049 BAILOUT("CatchExtensionObject"); | 3057 BAILOUT("CatchExtensionObject"); |
| 3050 } | 3058 } |
| 3051 | 3059 |
| (...skipping 23 matching lines...) Expand all Loading... |
| 3075 } | 3083 } |
| 3076 | 3084 |
| 3077 | 3085 |
| 3078 HInstruction* HGraphBuilder::BuildStoreNamedField(HValue* object, | 3086 HInstruction* HGraphBuilder::BuildStoreNamedField(HValue* object, |
| 3079 Handle<String> name, | 3087 Handle<String> name, |
| 3080 HValue* value, | 3088 HValue* value, |
| 3081 Handle<Map> type, | 3089 Handle<Map> type, |
| 3082 LookupResult* lookup, | 3090 LookupResult* lookup, |
| 3083 bool smi_and_map_check) { | 3091 bool smi_and_map_check) { |
| 3084 if (smi_and_map_check) { | 3092 if (smi_and_map_check) { |
| 3085 AddInstruction(new HCheckNonSmi(object)); | 3093 AddInstruction(new(zone()) HCheckNonSmi(object)); |
| 3086 AddInstruction(new HCheckMap(object, type)); | 3094 AddInstruction(new(zone()) HCheckMap(object, type)); |
| 3087 } | 3095 } |
| 3088 | 3096 |
| 3089 int index = ComputeStoredFieldIndex(type, name, lookup); | 3097 int index = ComputeStoredFieldIndex(type, name, lookup); |
| 3090 bool is_in_object = index < 0; | 3098 bool is_in_object = index < 0; |
| 3091 int offset = index * kPointerSize; | 3099 int offset = index * kPointerSize; |
| 3092 if (index < 0) { | 3100 if (index < 0) { |
| 3093 // Negative property indices are in-object properties, indexed | 3101 // Negative property indices are in-object properties, indexed |
| 3094 // from the end of the fixed part of the object. | 3102 // from the end of the fixed part of the object. |
| 3095 offset += type->instance_size(); | 3103 offset += type->instance_size(); |
| 3096 } else { | 3104 } else { |
| 3097 offset += FixedArray::kHeaderSize; | 3105 offset += FixedArray::kHeaderSize; |
| 3098 } | 3106 } |
| 3099 HStoreNamedField* instr = | 3107 HStoreNamedField* instr = |
| 3100 new HStoreNamedField(object, name, value, is_in_object, offset); | 3108 new(zone()) HStoreNamedField(object, name, value, is_in_object, offset); |
| 3101 if (lookup->type() == MAP_TRANSITION) { | 3109 if (lookup->type() == MAP_TRANSITION) { |
| 3102 Handle<Map> transition(lookup->GetTransitionMapFromMap(*type)); | 3110 Handle<Map> transition(lookup->GetTransitionMapFromMap(*type)); |
| 3103 instr->set_transition(transition); | 3111 instr->set_transition(transition); |
| 3104 // TODO(fschneider): Record the new map type of the object in the IR to | 3112 // TODO(fschneider): Record the new map type of the object in the IR to |
| 3105 // enable elimination of redundant checks after the transition store. | 3113 // enable elimination of redundant checks after the transition store. |
| 3106 instr->SetFlag(HValue::kChangesMaps); | 3114 instr->SetFlag(HValue::kChangesMaps); |
| 3107 } | 3115 } |
| 3108 return instr; | 3116 return instr; |
| 3109 } | 3117 } |
| 3110 | 3118 |
| 3111 | 3119 |
| 3112 HInstruction* HGraphBuilder::BuildStoreNamedGeneric(HValue* object, | 3120 HInstruction* HGraphBuilder::BuildStoreNamedGeneric(HValue* object, |
| 3113 Handle<String> name, | 3121 Handle<String> name, |
| 3114 HValue* value) { | 3122 HValue* value) { |
| 3115 HContext* context = new HContext; | 3123 HContext* context = new(zone()) HContext; |
| 3116 AddInstruction(context); | 3124 AddInstruction(context); |
| 3117 return new HStoreNamedGeneric(context, object, name, value); | 3125 return new(zone()) HStoreNamedGeneric(context, object, name, value); |
| 3118 } | 3126 } |
| 3119 | 3127 |
| 3120 | 3128 |
| 3121 HInstruction* HGraphBuilder::BuildStoreNamed(HValue* object, | 3129 HInstruction* HGraphBuilder::BuildStoreNamed(HValue* object, |
| 3122 HValue* value, | 3130 HValue* value, |
| 3123 Expression* expr) { | 3131 Expression* expr) { |
| 3124 Property* prop = (expr->AsProperty() != NULL) | 3132 Property* prop = (expr->AsProperty() != NULL) |
| 3125 ? expr->AsProperty() | 3133 ? expr->AsProperty() |
| 3126 : expr->AsAssignment()->target()->AsProperty(); | 3134 : expr->AsAssignment()->target()->AsProperty(); |
| 3127 Literal* key = prop->key()->AsLiteral(); | 3135 Literal* key = prop->key()->AsLiteral(); |
| (...skipping 20 matching lines...) Expand all Loading... |
| 3148 // TODO(ager): We should recognize when the prototype chains for different | 3156 // TODO(ager): We should recognize when the prototype chains for different |
| 3149 // maps are identical. In that case we can avoid repeatedly generating the | 3157 // maps are identical. In that case we can avoid repeatedly generating the |
| 3150 // same prototype map checks. | 3158 // same prototype map checks. |
| 3151 int count = 0; | 3159 int count = 0; |
| 3152 HBasicBlock* join = NULL; | 3160 HBasicBlock* join = NULL; |
| 3153 for (int i = 0; i < types->length() && count < kMaxStorePolymorphism; ++i) { | 3161 for (int i = 0; i < types->length() && count < kMaxStorePolymorphism; ++i) { |
| 3154 Handle<Map> map = types->at(i); | 3162 Handle<Map> map = types->at(i); |
| 3155 LookupResult lookup; | 3163 LookupResult lookup; |
| 3156 if (ComputeStoredField(map, name, &lookup)) { | 3164 if (ComputeStoredField(map, name, &lookup)) { |
| 3157 if (count == 0) { | 3165 if (count == 0) { |
| 3158 AddInstruction(new HCheckNonSmi(object)); // Only needed once. | 3166 AddInstruction(new(zone()) HCheckNonSmi(object)); // Only needed once. |
| 3159 join = graph()->CreateBasicBlock(); | 3167 join = graph()->CreateBasicBlock(); |
| 3160 } | 3168 } |
| 3161 ++count; | 3169 ++count; |
| 3162 HBasicBlock* if_true = graph()->CreateBasicBlock(); | 3170 HBasicBlock* if_true = graph()->CreateBasicBlock(); |
| 3163 HBasicBlock* if_false = graph()->CreateBasicBlock(); | 3171 HBasicBlock* if_false = graph()->CreateBasicBlock(); |
| 3164 HCompareMap* compare = new HCompareMap(object, map, if_true, if_false); | 3172 HCompareMap* compare = |
| 3173 new(zone()) HCompareMap(object, map, if_true, if_false); |
| 3165 current_block()->Finish(compare); | 3174 current_block()->Finish(compare); |
| 3166 | 3175 |
| 3167 set_current_block(if_true); | 3176 set_current_block(if_true); |
| 3168 HInstruction* instr = | 3177 HInstruction* instr = |
| 3169 BuildStoreNamedField(object, name, value, map, &lookup, false); | 3178 BuildStoreNamedField(object, name, value, map, &lookup, false); |
| 3170 instr->set_position(expr->position()); | 3179 instr->set_position(expr->position()); |
| 3171 // Goto will add the HSimulate for the store. | 3180 // Goto will add the HSimulate for the store. |
| 3172 AddInstruction(instr); | 3181 AddInstruction(instr); |
| 3173 if (!ast_context()->IsEffect()) Push(value); | 3182 if (!ast_context()->IsEffect()) Push(value); |
| 3174 current_block()->Goto(join); | 3183 current_block()->Goto(join); |
| (...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3289 void HGraphBuilder::HandleGlobalVariableAssignment(Variable* var, | 3298 void HGraphBuilder::HandleGlobalVariableAssignment(Variable* var, |
| 3290 HValue* value, | 3299 HValue* value, |
| 3291 int position, | 3300 int position, |
| 3292 int ast_id) { | 3301 int ast_id) { |
| 3293 LookupResult lookup; | 3302 LookupResult lookup; |
| 3294 GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, true); | 3303 GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, true); |
| 3295 if (type == kUseCell) { | 3304 if (type == kUseCell) { |
| 3296 bool check_hole = !lookup.IsDontDelete() || lookup.IsReadOnly(); | 3305 bool check_hole = !lookup.IsDontDelete() || lookup.IsReadOnly(); |
| 3297 Handle<GlobalObject> global(info()->global_object()); | 3306 Handle<GlobalObject> global(info()->global_object()); |
| 3298 Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(&lookup)); | 3307 Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(&lookup)); |
| 3299 HInstruction* instr = new HStoreGlobal(value, cell, check_hole); | 3308 HInstruction* instr = new(zone()) HStoreGlobalCell(value, cell, check_hole); |
| 3300 instr->set_position(position); | 3309 instr->set_position(position); |
| 3301 AddInstruction(instr); | 3310 AddInstruction(instr); |
| 3302 if (instr->HasSideEffects()) AddSimulate(ast_id); | 3311 if (instr->HasSideEffects()) AddSimulate(ast_id); |
| 3303 } else { | 3312 } else { |
| 3304 BAILOUT("global store only supported for cells"); | 3313 HContext* context = new(zone()) HContext; |
| 3314 AddInstruction(context); |
| 3315 HGlobalObject* global_object = new(zone()) HGlobalObject(context); |
| 3316 AddInstruction(global_object); |
| 3317 HStoreGlobalGeneric* instr = |
| 3318 new(zone()) HStoreGlobalGeneric(context, |
| 3319 global_object, |
| 3320 var->name(), |
| 3321 value); |
| 3322 instr->set_position(position); |
| 3323 AddInstruction(instr); |
| 3324 ASSERT(instr->HasSideEffects()); |
| 3325 if (instr->HasSideEffects()) AddSimulate(ast_id); |
| 3305 } | 3326 } |
| 3306 } | 3327 } |
| 3307 | 3328 |
| 3308 | 3329 |
| 3309 void HGraphBuilder::HandleCompoundAssignment(Assignment* expr) { | 3330 void HGraphBuilder::HandleCompoundAssignment(Assignment* expr) { |
| 3310 Expression* target = expr->target(); | 3331 Expression* target = expr->target(); |
| 3311 VariableProxy* proxy = target->AsVariableProxy(); | 3332 VariableProxy* proxy = target->AsVariableProxy(); |
| 3312 Variable* var = proxy->AsVariable(); | 3333 Variable* var = proxy->AsVariable(); |
| 3313 Property* prop = target->AsProperty(); | 3334 Property* prop = target->AsProperty(); |
| 3314 ASSERT(var == NULL || prop == NULL); | 3335 ASSERT(var == NULL || prop == NULL); |
| 3315 | 3336 |
| 3316 // We have a second position recorded in the FullCodeGenerator to have | 3337 // We have a second position recorded in the FullCodeGenerator to have |
| 3317 // type feedback for the binary operation. | 3338 // type feedback for the binary operation. |
| 3318 BinaryOperation* operation = expr->binary_operation(); | 3339 BinaryOperation* operation = expr->binary_operation(); |
| 3319 | 3340 |
| 3320 if (var != NULL) { | 3341 if (var != NULL) { |
| 3321 VISIT_FOR_VALUE(operation); | 3342 VISIT_FOR_VALUE(operation); |
| 3322 | 3343 |
| 3323 if (var->is_global()) { | 3344 if (var->is_global()) { |
| 3324 HandleGlobalVariableAssignment(var, | 3345 HandleGlobalVariableAssignment(var, |
| 3325 Top(), | 3346 Top(), |
| 3326 expr->position(), | 3347 expr->position(), |
| 3327 expr->AssignmentId()); | 3348 expr->AssignmentId()); |
| 3328 } else if (var->IsStackAllocated()) { | 3349 } else if (var->IsStackAllocated()) { |
| 3329 Bind(var, Top()); | 3350 Bind(var, Top()); |
| 3330 } else if (var->IsContextSlot()) { | 3351 } else if (var->IsContextSlot()) { |
| 3331 HValue* context = BuildContextChainWalk(var); | 3352 HValue* context = BuildContextChainWalk(var); |
| 3332 int index = var->AsSlot()->index(); | 3353 int index = var->AsSlot()->index(); |
| 3333 HStoreContextSlot* instr = new HStoreContextSlot(context, index, Top()); | 3354 HStoreContextSlot* instr = |
| 3355 new(zone()) HStoreContextSlot(context, index, Top()); |
| 3334 AddInstruction(instr); | 3356 AddInstruction(instr); |
| 3335 if (instr->HasSideEffects()) AddSimulate(expr->AssignmentId()); | 3357 if (instr->HasSideEffects()) AddSimulate(expr->AssignmentId()); |
| 3336 } else { | 3358 } else { |
| 3337 BAILOUT("compound assignment to lookup slot"); | 3359 BAILOUT("compound assignment to lookup slot"); |
| 3338 } | 3360 } |
| 3339 ast_context()->ReturnValue(Pop()); | 3361 ast_context()->ReturnValue(Pop()); |
| 3340 | 3362 |
| 3341 } else if (prop != NULL) { | 3363 } else if (prop != NULL) { |
| 3342 prop->RecordTypeFeedback(oracle()); | 3364 prop->RecordTypeFeedback(oracle()); |
| 3343 | 3365 |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3442 VISIT_FOR_VALUE(expr->value()); | 3464 VISIT_FOR_VALUE(expr->value()); |
| 3443 value = Pop(); | 3465 value = Pop(); |
| 3444 } | 3466 } |
| 3445 Bind(var, value); | 3467 Bind(var, value); |
| 3446 ast_context()->ReturnValue(value); | 3468 ast_context()->ReturnValue(value); |
| 3447 | 3469 |
| 3448 } else if (var->IsContextSlot() && var->mode() != Variable::CONST) { | 3470 } else if (var->IsContextSlot() && var->mode() != Variable::CONST) { |
| 3449 VISIT_FOR_VALUE(expr->value()); | 3471 VISIT_FOR_VALUE(expr->value()); |
| 3450 HValue* context = BuildContextChainWalk(var); | 3472 HValue* context = BuildContextChainWalk(var); |
| 3451 int index = var->AsSlot()->index(); | 3473 int index = var->AsSlot()->index(); |
| 3452 HStoreContextSlot* instr = new HStoreContextSlot(context, index, Top()); | 3474 HStoreContextSlot* instr = |
| 3475 new(zone()) HStoreContextSlot(context, index, Top()); |
| 3453 AddInstruction(instr); | 3476 AddInstruction(instr); |
| 3454 if (instr->HasSideEffects()) AddSimulate(expr->AssignmentId()); | 3477 if (instr->HasSideEffects()) AddSimulate(expr->AssignmentId()); |
| 3455 ast_context()->ReturnValue(Pop()); | 3478 ast_context()->ReturnValue(Pop()); |
| 3456 | 3479 |
| 3457 } else if (var->is_global()) { | 3480 } else if (var->is_global()) { |
| 3458 VISIT_FOR_VALUE(expr->value()); | 3481 VISIT_FOR_VALUE(expr->value()); |
| 3459 HandleGlobalVariableAssignment(var, | 3482 HandleGlobalVariableAssignment(var, |
| 3460 Top(), | 3483 Top(), |
| 3461 expr->position(), | 3484 expr->position(), |
| 3462 expr->AssignmentId()); | 3485 expr->AssignmentId()); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 3475 | 3498 |
| 3476 | 3499 |
| 3477 void HGraphBuilder::VisitThrow(Throw* expr) { | 3500 void HGraphBuilder::VisitThrow(Throw* expr) { |
| 3478 // We don't optimize functions with invalid left-hand sides in | 3501 // We don't optimize functions with invalid left-hand sides in |
| 3479 // assignments, count operations, or for-in. Consequently throw can | 3502 // assignments, count operations, or for-in. Consequently throw can |
| 3480 // currently only occur in an effect context. | 3503 // currently only occur in an effect context. |
| 3481 ASSERT(ast_context()->IsEffect()); | 3504 ASSERT(ast_context()->IsEffect()); |
| 3482 VISIT_FOR_VALUE(expr->exception()); | 3505 VISIT_FOR_VALUE(expr->exception()); |
| 3483 | 3506 |
| 3484 HValue* value = environment()->Pop(); | 3507 HValue* value = environment()->Pop(); |
| 3485 HThrow* instr = new HThrow(value); | 3508 HThrow* instr = new(zone()) HThrow(value); |
| 3486 instr->set_position(expr->position()); | 3509 instr->set_position(expr->position()); |
| 3487 AddInstruction(instr); | 3510 AddInstruction(instr); |
| 3488 AddSimulate(expr->id()); | 3511 AddSimulate(expr->id()); |
| 3489 current_block()->FinishExit(new HAbnormalExit); | 3512 current_block()->FinishExit(new(zone()) HAbnormalExit); |
| 3490 set_current_block(NULL); | 3513 set_current_block(NULL); |
| 3491 } | 3514 } |
| 3492 | 3515 |
| 3493 | 3516 |
| 3494 HLoadNamedField* HGraphBuilder::BuildLoadNamedField(HValue* object, | 3517 HLoadNamedField* HGraphBuilder::BuildLoadNamedField(HValue* object, |
| 3495 Property* expr, | 3518 Property* expr, |
| 3496 Handle<Map> type, | 3519 Handle<Map> type, |
| 3497 LookupResult* lookup, | 3520 LookupResult* lookup, |
| 3498 bool smi_and_map_check) { | 3521 bool smi_and_map_check) { |
| 3499 if (smi_and_map_check) { | 3522 if (smi_and_map_check) { |
| 3500 AddInstruction(new HCheckNonSmi(object)); | 3523 AddInstruction(new(zone()) HCheckNonSmi(object)); |
| 3501 AddInstruction(new HCheckMap(object, type)); | 3524 AddInstruction(new(zone()) HCheckMap(object, type)); |
| 3502 } | 3525 } |
| 3503 | 3526 |
| 3504 int index = lookup->GetLocalFieldIndexFromMap(*type); | 3527 int index = lookup->GetLocalFieldIndexFromMap(*type); |
| 3505 if (index < 0) { | 3528 if (index < 0) { |
| 3506 // Negative property indices are in-object properties, indexed | 3529 // Negative property indices are in-object properties, indexed |
| 3507 // from the end of the fixed part of the object. | 3530 // from the end of the fixed part of the object. |
| 3508 int offset = (index * kPointerSize) + type->instance_size(); | 3531 int offset = (index * kPointerSize) + type->instance_size(); |
| 3509 return new HLoadNamedField(object, true, offset); | 3532 return new(zone()) HLoadNamedField(object, true, offset); |
| 3510 } else { | 3533 } else { |
| 3511 // Non-negative property indices are in the properties array. | 3534 // Non-negative property indices are in the properties array. |
| 3512 int offset = (index * kPointerSize) + FixedArray::kHeaderSize; | 3535 int offset = (index * kPointerSize) + FixedArray::kHeaderSize; |
| 3513 return new HLoadNamedField(object, false, offset); | 3536 return new(zone()) HLoadNamedField(object, false, offset); |
| 3514 } | 3537 } |
| 3515 } | 3538 } |
| 3516 | 3539 |
| 3517 | 3540 |
| 3518 HInstruction* HGraphBuilder::BuildLoadNamedGeneric(HValue* obj, | 3541 HInstruction* HGraphBuilder::BuildLoadNamedGeneric(HValue* obj, |
| 3519 Property* expr) { | 3542 Property* expr) { |
| 3520 ASSERT(expr->key()->IsPropertyName()); | 3543 ASSERT(expr->key()->IsPropertyName()); |
| 3521 Handle<Object> name = expr->key()->AsLiteral()->handle(); | 3544 Handle<Object> name = expr->key()->AsLiteral()->handle(); |
| 3522 HContext* context = new HContext; | 3545 HContext* context = new(zone()) HContext; |
| 3523 AddInstruction(context); | 3546 AddInstruction(context); |
| 3524 return new HLoadNamedGeneric(context, obj, name); | 3547 return new(zone()) HLoadNamedGeneric(context, obj, name); |
| 3525 } | 3548 } |
| 3526 | 3549 |
| 3527 | 3550 |
| 3528 HInstruction* HGraphBuilder::BuildLoadNamed(HValue* obj, | 3551 HInstruction* HGraphBuilder::BuildLoadNamed(HValue* obj, |
| 3529 Property* expr, | 3552 Property* expr, |
| 3530 Handle<Map> map, | 3553 Handle<Map> map, |
| 3531 Handle<String> name) { | 3554 Handle<String> name) { |
| 3532 LookupResult lookup; | 3555 LookupResult lookup; |
| 3533 map->LookupInDescriptors(NULL, *name, &lookup); | 3556 map->LookupInDescriptors(NULL, *name, &lookup); |
| 3534 if (lookup.IsProperty() && lookup.type() == FIELD) { | 3557 if (lookup.IsProperty() && lookup.type() == FIELD) { |
| 3535 return BuildLoadNamedField(obj, | 3558 return BuildLoadNamedField(obj, |
| 3536 expr, | 3559 expr, |
| 3537 map, | 3560 map, |
| 3538 &lookup, | 3561 &lookup, |
| 3539 true); | 3562 true); |
| 3540 } else if (lookup.IsProperty() && lookup.type() == CONSTANT_FUNCTION) { | 3563 } else if (lookup.IsProperty() && lookup.type() == CONSTANT_FUNCTION) { |
| 3541 AddInstruction(new HCheckNonSmi(obj)); | 3564 AddInstruction(new(zone()) HCheckNonSmi(obj)); |
| 3542 AddInstruction(new HCheckMap(obj, map)); | 3565 AddInstruction(new(zone()) HCheckMap(obj, map)); |
| 3543 Handle<JSFunction> function(lookup.GetConstantFunctionFromMap(*map)); | 3566 Handle<JSFunction> function(lookup.GetConstantFunctionFromMap(*map)); |
| 3544 return new HConstant(function, Representation::Tagged()); | 3567 return new(zone()) HConstant(function, Representation::Tagged()); |
| 3545 } else { | 3568 } else { |
| 3546 return BuildLoadNamedGeneric(obj, expr); | 3569 return BuildLoadNamedGeneric(obj, expr); |
| 3547 } | 3570 } |
| 3548 } | 3571 } |
| 3549 | 3572 |
| 3550 | 3573 |
| 3551 HInstruction* HGraphBuilder::BuildLoadKeyedGeneric(HValue* object, | 3574 HInstruction* HGraphBuilder::BuildLoadKeyedGeneric(HValue* object, |
| 3552 HValue* key) { | 3575 HValue* key) { |
| 3553 HContext* context = new HContext; | 3576 HContext* context = new(zone()) HContext; |
| 3554 AddInstruction(context); | 3577 AddInstruction(context); |
| 3555 return new HLoadKeyedGeneric(context, object, key); | 3578 return new(zone()) HLoadKeyedGeneric(context, object, key); |
| 3556 } | 3579 } |
| 3557 | 3580 |
| 3558 | 3581 |
| 3559 HInstruction* HGraphBuilder::BuildLoadKeyedFastElement(HValue* object, | 3582 HInstruction* HGraphBuilder::BuildLoadKeyedFastElement(HValue* object, |
| 3560 HValue* key, | 3583 HValue* key, |
| 3561 Property* expr) { | 3584 Property* expr) { |
| 3562 ASSERT(!expr->key()->IsPropertyName() && expr->IsMonomorphic()); | 3585 ASSERT(!expr->key()->IsPropertyName() && expr->IsMonomorphic()); |
| 3563 AddInstruction(new HCheckNonSmi(object)); | 3586 AddInstruction(new(zone()) HCheckNonSmi(object)); |
| 3564 Handle<Map> map = expr->GetMonomorphicReceiverType(); | 3587 Handle<Map> map = expr->GetMonomorphicReceiverType(); |
| 3565 ASSERT(map->has_fast_elements()); | 3588 ASSERT(map->has_fast_elements()); |
| 3566 AddInstruction(new HCheckMap(object, map)); | 3589 AddInstruction(new(zone()) HCheckMap(object, map)); |
| 3567 bool is_array = (map->instance_type() == JS_ARRAY_TYPE); | 3590 bool is_array = (map->instance_type() == JS_ARRAY_TYPE); |
| 3568 HLoadElements* elements = new HLoadElements(object); | 3591 HLoadElements* elements = new(zone()) HLoadElements(object); |
| 3569 HInstruction* length = NULL; | 3592 HInstruction* length = NULL; |
| 3570 if (is_array) { | 3593 if (is_array) { |
| 3571 length = AddInstruction(new HJSArrayLength(object)); | 3594 length = AddInstruction(new(zone()) HJSArrayLength(object)); |
| 3572 AddInstruction(new HBoundsCheck(key, length)); | 3595 AddInstruction(new(zone()) HBoundsCheck(key, length)); |
| 3573 AddInstruction(elements); | 3596 AddInstruction(elements); |
| 3574 } else { | 3597 } else { |
| 3575 AddInstruction(elements); | 3598 AddInstruction(elements); |
| 3576 length = AddInstruction(new HFixedArrayLength(elements)); | 3599 length = AddInstruction(new(zone()) HFixedArrayLength(elements)); |
| 3577 AddInstruction(new HBoundsCheck(key, length)); | 3600 AddInstruction(new(zone()) HBoundsCheck(key, length)); |
| 3578 } | 3601 } |
| 3579 return new HLoadKeyedFastElement(elements, key); | 3602 return new(zone()) HLoadKeyedFastElement(elements, key); |
| 3580 } | 3603 } |
| 3581 | 3604 |
| 3582 | 3605 |
| 3583 HInstruction* HGraphBuilder::BuildLoadKeyedSpecializedArrayElement( | 3606 HInstruction* HGraphBuilder::BuildLoadKeyedSpecializedArrayElement( |
| 3584 HValue* object, | 3607 HValue* object, |
| 3585 HValue* key, | 3608 HValue* key, |
| 3586 Property* expr) { | 3609 Property* expr) { |
| 3587 ASSERT(!expr->key()->IsPropertyName() && expr->IsMonomorphic()); | 3610 ASSERT(!expr->key()->IsPropertyName() && expr->IsMonomorphic()); |
| 3588 AddInstruction(new HCheckNonSmi(object)); | 3611 AddInstruction(new(zone()) HCheckNonSmi(object)); |
| 3589 Handle<Map> map = expr->GetMonomorphicReceiverType(); | 3612 Handle<Map> map = expr->GetMonomorphicReceiverType(); |
| 3590 ASSERT(!map->has_fast_elements()); | 3613 ASSERT(!map->has_fast_elements()); |
| 3591 ASSERT(map->has_external_array_elements()); | 3614 ASSERT(map->has_external_array_elements()); |
| 3592 AddInstruction(new HCheckMap(object, map)); | 3615 AddInstruction(new(zone()) HCheckMap(object, map)); |
| 3593 HLoadElements* elements = new HLoadElements(object); | 3616 HLoadElements* elements = new(zone()) HLoadElements(object); |
| 3594 AddInstruction(elements); | 3617 AddInstruction(elements); |
| 3595 HInstruction* length = new HExternalArrayLength(elements); | 3618 HInstruction* length = new(zone()) HExternalArrayLength(elements); |
| 3596 AddInstruction(length); | 3619 AddInstruction(length); |
| 3597 AddInstruction(new HBoundsCheck(key, length)); | 3620 AddInstruction(new(zone()) HBoundsCheck(key, length)); |
| 3598 HLoadExternalArrayPointer* external_elements = | 3621 HLoadExternalArrayPointer* external_elements = |
| 3599 new HLoadExternalArrayPointer(elements); | 3622 new(zone()) HLoadExternalArrayPointer(elements); |
| 3600 AddInstruction(external_elements); | 3623 AddInstruction(external_elements); |
| 3601 HLoadKeyedSpecializedArrayElement* pixel_array_value = | 3624 HLoadKeyedSpecializedArrayElement* pixel_array_value = |
| 3602 new HLoadKeyedSpecializedArrayElement(external_elements, | 3625 new(zone()) HLoadKeyedSpecializedArrayElement( |
| 3603 key, | 3626 external_elements, key, expr->GetExternalArrayType()); |
| 3604 expr->GetExternalArrayType()); | |
| 3605 return pixel_array_value; | 3627 return pixel_array_value; |
| 3606 } | 3628 } |
| 3607 | 3629 |
| 3608 | 3630 |
| 3609 HInstruction* HGraphBuilder::BuildStoreKeyedGeneric(HValue* object, | 3631 HInstruction* HGraphBuilder::BuildStoreKeyedGeneric(HValue* object, |
| 3610 HValue* key, | 3632 HValue* key, |
| 3611 HValue* value) { | 3633 HValue* value) { |
| 3612 HContext* context = new HContext; | 3634 HContext* context = new(zone()) HContext; |
| 3613 AddInstruction(context); | 3635 AddInstruction(context); |
| 3614 return new HStoreKeyedGeneric(context, object, key, value); | 3636 return new(zone()) HStoreKeyedGeneric(context, object, key, value); |
| 3615 } | 3637 } |
| 3616 | 3638 |
| 3617 | 3639 |
| 3618 HInstruction* HGraphBuilder::BuildStoreKeyedFastElement(HValue* object, | 3640 HInstruction* HGraphBuilder::BuildStoreKeyedFastElement(HValue* object, |
| 3619 HValue* key, | 3641 HValue* key, |
| 3620 HValue* val, | 3642 HValue* val, |
| 3621 Expression* expr) { | 3643 Expression* expr) { |
| 3622 ASSERT(expr->IsMonomorphic()); | 3644 ASSERT(expr->IsMonomorphic()); |
| 3623 AddInstruction(new HCheckNonSmi(object)); | 3645 AddInstruction(new(zone()) HCheckNonSmi(object)); |
| 3624 Handle<Map> map = expr->GetMonomorphicReceiverType(); | 3646 Handle<Map> map = expr->GetMonomorphicReceiverType(); |
| 3625 ASSERT(map->has_fast_elements()); | 3647 ASSERT(map->has_fast_elements()); |
| 3626 AddInstruction(new HCheckMap(object, map)); | 3648 AddInstruction(new(zone()) HCheckMap(object, map)); |
| 3627 HInstruction* elements = AddInstruction(new HLoadElements(object)); | 3649 HInstruction* elements = AddInstruction(new(zone()) HLoadElements(object)); |
| 3628 AddInstruction(new HCheckMap(elements, | 3650 AddInstruction(new(zone()) HCheckMap( |
| 3629 isolate()->factory()->fixed_array_map())); | 3651 elements, isolate()->factory()->fixed_array_map())); |
| 3630 bool is_array = (map->instance_type() == JS_ARRAY_TYPE); | 3652 bool is_array = (map->instance_type() == JS_ARRAY_TYPE); |
| 3631 HInstruction* length = NULL; | 3653 HInstruction* length = NULL; |
| 3632 if (is_array) { | 3654 if (is_array) { |
| 3633 length = AddInstruction(new HJSArrayLength(object)); | 3655 length = AddInstruction(new(zone()) HJSArrayLength(object)); |
| 3634 } else { | 3656 } else { |
| 3635 length = AddInstruction(new HFixedArrayLength(elements)); | 3657 length = AddInstruction(new(zone()) HFixedArrayLength(elements)); |
| 3636 } | 3658 } |
| 3637 AddInstruction(new HBoundsCheck(key, length)); | 3659 AddInstruction(new(zone()) HBoundsCheck(key, length)); |
| 3638 return new HStoreKeyedFastElement(elements, key, val); | 3660 return new(zone()) HStoreKeyedFastElement(elements, key, val); |
| 3639 } | 3661 } |
| 3640 | 3662 |
| 3641 | 3663 |
| 3642 HInstruction* HGraphBuilder::BuildStoreKeyedSpecializedArrayElement( | 3664 HInstruction* HGraphBuilder::BuildStoreKeyedSpecializedArrayElement( |
| 3643 HValue* object, | 3665 HValue* object, |
| 3644 HValue* key, | 3666 HValue* key, |
| 3645 HValue* val, | 3667 HValue* val, |
| 3646 Assignment* expr) { | 3668 Assignment* expr) { |
| 3647 ASSERT(expr->IsMonomorphic()); | 3669 ASSERT(expr->IsMonomorphic()); |
| 3648 AddInstruction(new HCheckNonSmi(object)); | 3670 AddInstruction(new(zone()) HCheckNonSmi(object)); |
| 3649 Handle<Map> map = expr->GetMonomorphicReceiverType(); | 3671 Handle<Map> map = expr->GetMonomorphicReceiverType(); |
| 3650 ASSERT(!map->has_fast_elements()); | 3672 ASSERT(!map->has_fast_elements()); |
| 3651 ASSERT(map->has_external_array_elements()); | 3673 ASSERT(map->has_external_array_elements()); |
| 3652 AddInstruction(new HCheckMap(object, map)); | 3674 AddInstruction(new(zone()) HCheckMap(object, map)); |
| 3653 HLoadElements* elements = new HLoadElements(object); | 3675 HLoadElements* elements = new(zone()) HLoadElements(object); |
| 3654 AddInstruction(elements); | 3676 AddInstruction(elements); |
| 3655 HInstruction* length = AddInstruction(new HExternalArrayLength(elements)); | 3677 HInstruction* length = AddInstruction( |
| 3656 AddInstruction(new HBoundsCheck(key, length)); | 3678 new(zone()) HExternalArrayLength(elements)); |
| 3679 AddInstruction(new(zone()) HBoundsCheck(key, length)); |
| 3657 HLoadExternalArrayPointer* external_elements = | 3680 HLoadExternalArrayPointer* external_elements = |
| 3658 new HLoadExternalArrayPointer(elements); | 3681 new(zone()) HLoadExternalArrayPointer(elements); |
| 3659 AddInstruction(external_elements); | 3682 AddInstruction(external_elements); |
| 3660 return new HStoreKeyedSpecializedArrayElement( | 3683 return new(zone()) HStoreKeyedSpecializedArrayElement( |
| 3661 external_elements, | 3684 external_elements, |
| 3662 key, | 3685 key, |
| 3663 val, | 3686 val, |
| 3664 expr->GetExternalArrayType()); | 3687 expr->GetExternalArrayType()); |
| 3665 } | 3688 } |
| 3666 | 3689 |
| 3667 | 3690 |
| 3668 bool HGraphBuilder::TryArgumentsAccess(Property* expr) { | 3691 bool HGraphBuilder::TryArgumentsAccess(Property* expr) { |
| 3669 VariableProxy* proxy = expr->obj()->AsVariableProxy(); | 3692 VariableProxy* proxy = expr->obj()->AsVariableProxy(); |
| 3670 if (proxy == NULL) return false; | 3693 if (proxy == NULL) return false; |
| 3671 if (!proxy->var()->IsStackAllocated()) return false; | 3694 if (!proxy->var()->IsStackAllocated()) return false; |
| 3672 if (!environment()->Lookup(proxy->var())->CheckFlag(HValue::kIsArguments)) { | 3695 if (!environment()->Lookup(proxy->var())->CheckFlag(HValue::kIsArguments)) { |
| 3673 return false; | 3696 return false; |
| 3674 } | 3697 } |
| 3675 | 3698 |
| 3676 HInstruction* result = NULL; | 3699 HInstruction* result = NULL; |
| 3677 if (expr->key()->IsPropertyName()) { | 3700 if (expr->key()->IsPropertyName()) { |
| 3678 Handle<String> name = expr->key()->AsLiteral()->AsPropertyName(); | 3701 Handle<String> name = expr->key()->AsLiteral()->AsPropertyName(); |
| 3679 if (!name->IsEqualTo(CStrVector("length"))) return false; | 3702 if (!name->IsEqualTo(CStrVector("length"))) return false; |
| 3680 HInstruction* elements = AddInstruction(new HArgumentsElements); | 3703 HInstruction* elements = AddInstruction(new(zone()) HArgumentsElements); |
| 3681 result = new HArgumentsLength(elements); | 3704 result = new(zone()) HArgumentsLength(elements); |
| 3682 } else { | 3705 } else { |
| 3683 Push(graph()->GetArgumentsObject()); | 3706 Push(graph()->GetArgumentsObject()); |
| 3684 VisitForValue(expr->key()); | 3707 VisitForValue(expr->key()); |
| 3685 if (HasStackOverflow()) return false; | 3708 if (HasStackOverflow()) return false; |
| 3686 HValue* key = Pop(); | 3709 HValue* key = Pop(); |
| 3687 Drop(1); // Arguments object. | 3710 Drop(1); // Arguments object. |
| 3688 HInstruction* elements = AddInstruction(new HArgumentsElements); | 3711 HInstruction* elements = AddInstruction(new(zone()) HArgumentsElements); |
| 3689 HInstruction* length = AddInstruction(new HArgumentsLength(elements)); | 3712 HInstruction* length = AddInstruction( |
| 3690 AddInstruction(new HBoundsCheck(key, length)); | 3713 new(zone()) HArgumentsLength(elements)); |
| 3691 result = new HAccessArgumentsAt(elements, length, key); | 3714 AddInstruction(new(zone()) HBoundsCheck(key, length)); |
| 3715 result = new(zone()) HAccessArgumentsAt(elements, length, key); |
| 3692 } | 3716 } |
| 3693 ast_context()->ReturnInstruction(result, expr->id()); | 3717 ast_context()->ReturnInstruction(result, expr->id()); |
| 3694 return true; | 3718 return true; |
| 3695 } | 3719 } |
| 3696 | 3720 |
| 3697 | 3721 |
| 3698 void HGraphBuilder::VisitProperty(Property* expr) { | 3722 void HGraphBuilder::VisitProperty(Property* expr) { |
| 3699 expr->RecordTypeFeedback(oracle()); | 3723 expr->RecordTypeFeedback(oracle()); |
| 3700 | 3724 |
| 3701 if (TryArgumentsAccess(expr)) return; | 3725 if (TryArgumentsAccess(expr)) return; |
| 3702 CHECK_BAILOUT; | 3726 CHECK_BAILOUT; |
| 3703 | 3727 |
| 3704 VISIT_FOR_VALUE(expr->obj()); | 3728 VISIT_FOR_VALUE(expr->obj()); |
| 3705 | 3729 |
| 3706 HInstruction* instr = NULL; | 3730 HInstruction* instr = NULL; |
| 3707 if (expr->IsArrayLength()) { | 3731 if (expr->IsArrayLength()) { |
| 3708 HValue* array = Pop(); | 3732 HValue* array = Pop(); |
| 3709 AddInstruction(new HCheckNonSmi(array)); | 3733 AddInstruction(new(zone()) HCheckNonSmi(array)); |
| 3710 AddInstruction(new HCheckInstanceType(array, JS_ARRAY_TYPE, JS_ARRAY_TYPE)); | 3734 AddInstruction(new(zone()) HCheckInstanceType(array, |
| 3711 instr = new HJSArrayLength(array); | 3735 JS_ARRAY_TYPE, |
| 3736 JS_ARRAY_TYPE)); |
| 3737 instr = new(zone()) HJSArrayLength(array); |
| 3712 | 3738 |
| 3713 } else if (expr->IsStringLength()) { | 3739 } else if (expr->IsStringLength()) { |
| 3714 HValue* string = Pop(); | 3740 HValue* string = Pop(); |
| 3715 AddInstruction(new HCheckNonSmi(string)); | 3741 AddInstruction(new(zone()) HCheckNonSmi(string)); |
| 3716 AddInstruction(new HCheckInstanceType(string, | 3742 AddInstruction(new(zone()) HCheckInstanceType(string, |
| 3717 FIRST_STRING_TYPE, | 3743 FIRST_STRING_TYPE, |
| 3718 LAST_STRING_TYPE)); | 3744 LAST_STRING_TYPE)); |
| 3719 instr = new HStringLength(string); | 3745 instr = new(zone()) HStringLength(string); |
| 3720 } else if (expr->IsStringAccess()) { | 3746 } else if (expr->IsStringAccess()) { |
| 3721 VISIT_FOR_VALUE(expr->key()); | 3747 VISIT_FOR_VALUE(expr->key()); |
| 3722 HValue* index = Pop(); | 3748 HValue* index = Pop(); |
| 3723 HValue* string = Pop(); | 3749 HValue* string = Pop(); |
| 3724 HStringCharCodeAt* char_code = BuildStringCharCodeAt(string, index); | 3750 HStringCharCodeAt* char_code = BuildStringCharCodeAt(string, index); |
| 3725 AddInstruction(char_code); | 3751 AddInstruction(char_code); |
| 3726 instr = new HStringCharFromCode(char_code); | 3752 instr = new(zone()) HStringCharFromCode(char_code); |
| 3727 | 3753 |
| 3728 } else if (expr->IsFunctionPrototype()) { | 3754 } else if (expr->IsFunctionPrototype()) { |
| 3729 HValue* function = Pop(); | 3755 HValue* function = Pop(); |
| 3730 AddInstruction(new HCheckNonSmi(function)); | 3756 AddInstruction(new(zone()) HCheckNonSmi(function)); |
| 3731 instr = new HLoadFunctionPrototype(function); | 3757 instr = new(zone()) HLoadFunctionPrototype(function); |
| 3732 | 3758 |
| 3733 } else if (expr->key()->IsPropertyName()) { | 3759 } else if (expr->key()->IsPropertyName()) { |
| 3734 Handle<String> name = expr->key()->AsLiteral()->AsPropertyName(); | 3760 Handle<String> name = expr->key()->AsLiteral()->AsPropertyName(); |
| 3735 ZoneMapList* types = expr->GetReceiverTypes(); | 3761 ZoneMapList* types = expr->GetReceiverTypes(); |
| 3736 | 3762 |
| 3737 HValue* obj = Pop(); | 3763 HValue* obj = Pop(); |
| 3738 if (expr->IsMonomorphic()) { | 3764 if (expr->IsMonomorphic()) { |
| 3739 instr = BuildLoadNamed(obj, expr, types->first(), name); | 3765 instr = BuildLoadNamed(obj, expr, types->first(), name); |
| 3740 } else if (types != NULL && types->length() > 1) { | 3766 } else if (types != NULL && types->length() > 1) { |
| 3741 AddInstruction(new HCheckNonSmi(obj)); | 3767 AddInstruction(new(zone()) HCheckNonSmi(obj)); |
| 3742 instr = new HLoadNamedFieldPolymorphic(obj, types, name); | 3768 instr = new(zone()) HLoadNamedFieldPolymorphic(obj, types, name); |
| 3743 } else { | 3769 } else { |
| 3744 instr = BuildLoadNamedGeneric(obj, expr); | 3770 instr = BuildLoadNamedGeneric(obj, expr); |
| 3745 } | 3771 } |
| 3746 | 3772 |
| 3747 } else { | 3773 } else { |
| 3748 VISIT_FOR_VALUE(expr->key()); | 3774 VISIT_FOR_VALUE(expr->key()); |
| 3749 | 3775 |
| 3750 HValue* key = Pop(); | 3776 HValue* key = Pop(); |
| 3751 HValue* obj = Pop(); | 3777 HValue* obj = Pop(); |
| 3752 | 3778 |
| (...skipping 18 matching lines...) Expand all Loading... |
| 3771 | 3797 |
| 3772 | 3798 |
| 3773 void HGraphBuilder::AddCheckConstantFunction(Call* expr, | 3799 void HGraphBuilder::AddCheckConstantFunction(Call* expr, |
| 3774 HValue* receiver, | 3800 HValue* receiver, |
| 3775 Handle<Map> receiver_map, | 3801 Handle<Map> receiver_map, |
| 3776 bool smi_and_map_check) { | 3802 bool smi_and_map_check) { |
| 3777 // Constant functions have the nice property that the map will change if they | 3803 // Constant functions have the nice property that the map will change if they |
| 3778 // are overwritten. Therefore it is enough to check the map of the holder and | 3804 // are overwritten. Therefore it is enough to check the map of the holder and |
| 3779 // its prototypes. | 3805 // its prototypes. |
| 3780 if (smi_and_map_check) { | 3806 if (smi_and_map_check) { |
| 3781 AddInstruction(new HCheckNonSmi(receiver)); | 3807 AddInstruction(new(zone()) HCheckNonSmi(receiver)); |
| 3782 AddInstruction(new HCheckMap(receiver, receiver_map)); | 3808 AddInstruction(new(zone()) HCheckMap(receiver, receiver_map)); |
| 3783 } | 3809 } |
| 3784 if (!expr->holder().is_null()) { | 3810 if (!expr->holder().is_null()) { |
| 3785 AddInstruction(new HCheckPrototypeMaps( | 3811 AddInstruction(new(zone()) HCheckPrototypeMaps( |
| 3786 Handle<JSObject>(JSObject::cast(receiver_map->prototype())), | 3812 Handle<JSObject>(JSObject::cast(receiver_map->prototype())), |
| 3787 expr->holder())); | 3813 expr->holder())); |
| 3788 } | 3814 } |
| 3789 } | 3815 } |
| 3790 | 3816 |
| 3791 | 3817 |
| 3792 void HGraphBuilder::HandlePolymorphicCallNamed(Call* expr, | 3818 void HGraphBuilder::HandlePolymorphicCallNamed(Call* expr, |
| 3793 HValue* receiver, | 3819 HValue* receiver, |
| 3794 ZoneMapList* types, | 3820 ZoneMapList* types, |
| 3795 Handle<String> name) { | 3821 Handle<String> name) { |
| 3796 // TODO(ager): We should recognize when the prototype chains for different | 3822 // TODO(ager): We should recognize when the prototype chains for different |
| 3797 // maps are identical. In that case we can avoid repeatedly generating the | 3823 // maps are identical. In that case we can avoid repeatedly generating the |
| 3798 // same prototype map checks. | 3824 // same prototype map checks. |
| 3799 int argument_count = expr->arguments()->length() + 1; // Includes receiver. | 3825 int argument_count = expr->arguments()->length() + 1; // Includes receiver. |
| 3800 int count = 0; | 3826 int count = 0; |
| 3801 HBasicBlock* join = NULL; | 3827 HBasicBlock* join = NULL; |
| 3802 for (int i = 0; i < types->length() && count < kMaxCallPolymorphism; ++i) { | 3828 for (int i = 0; i < types->length() && count < kMaxCallPolymorphism; ++i) { |
| 3803 Handle<Map> map = types->at(i); | 3829 Handle<Map> map = types->at(i); |
| 3804 if (expr->ComputeTarget(map, name)) { | 3830 if (expr->ComputeTarget(map, name)) { |
| 3805 if (count == 0) { | 3831 if (count == 0) { |
| 3806 AddInstruction(new HCheckNonSmi(receiver)); // Only needed once. | 3832 // Only needed once. |
| 3833 AddInstruction(new(zone()) HCheckNonSmi(receiver)); |
| 3807 join = graph()->CreateBasicBlock(); | 3834 join = graph()->CreateBasicBlock(); |
| 3808 } | 3835 } |
| 3809 ++count; | 3836 ++count; |
| 3810 HBasicBlock* if_true = graph()->CreateBasicBlock(); | 3837 HBasicBlock* if_true = graph()->CreateBasicBlock(); |
| 3811 HBasicBlock* if_false = graph()->CreateBasicBlock(); | 3838 HBasicBlock* if_false = graph()->CreateBasicBlock(); |
| 3812 HCompareMap* compare = new HCompareMap(receiver, map, if_true, if_false); | 3839 HCompareMap* compare = |
| 3840 new(zone()) HCompareMap(receiver, map, if_true, if_false); |
| 3813 current_block()->Finish(compare); | 3841 current_block()->Finish(compare); |
| 3814 | 3842 |
| 3815 set_current_block(if_true); | 3843 set_current_block(if_true); |
| 3816 AddCheckConstantFunction(expr, receiver, map, false); | 3844 AddCheckConstantFunction(expr, receiver, map, false); |
| 3817 if (FLAG_trace_inlining && FLAG_polymorphic_inlining) { | 3845 if (FLAG_trace_inlining && FLAG_polymorphic_inlining) { |
| 3818 PrintF("Trying to inline the polymorphic call to %s\n", | 3846 PrintF("Trying to inline the polymorphic call to %s\n", |
| 3819 *name->ToCString()); | 3847 *name->ToCString()); |
| 3820 } | 3848 } |
| 3821 if (!FLAG_polymorphic_inlining || !TryInline(expr)) { | 3849 if (!FLAG_polymorphic_inlining || !TryInline(expr)) { |
| 3822 // Check for bailout, as trying to inline might fail due to bailout | 3850 // Check for bailout, as trying to inline might fail due to bailout |
| 3823 // during hydrogen processing. | 3851 // during hydrogen processing. |
| 3824 CHECK_BAILOUT; | 3852 CHECK_BAILOUT; |
| 3825 HCallConstantFunction* call = | 3853 HCallConstantFunction* call = |
| 3826 new HCallConstantFunction(expr->target(), argument_count); | 3854 new(zone()) HCallConstantFunction(expr->target(), argument_count); |
| 3827 call->set_position(expr->position()); | 3855 call->set_position(expr->position()); |
| 3828 PreProcessCall(call); | 3856 PreProcessCall(call); |
| 3829 AddInstruction(call); | 3857 AddInstruction(call); |
| 3830 if (!ast_context()->IsEffect()) Push(call); | 3858 if (!ast_context()->IsEffect()) Push(call); |
| 3831 } | 3859 } |
| 3832 | 3860 |
| 3833 if (current_block() != NULL) current_block()->Goto(join); | 3861 if (current_block() != NULL) current_block()->Goto(join); |
| 3834 set_current_block(if_false); | 3862 set_current_block(if_false); |
| 3835 } | 3863 } |
| 3836 } | 3864 } |
| 3837 | 3865 |
| 3838 // Finish up. Unconditionally deoptimize if we've handled all the maps we | 3866 // Finish up. Unconditionally deoptimize if we've handled all the maps we |
| 3839 // know about and do not want to handle ones we've never seen. Otherwise | 3867 // know about and do not want to handle ones we've never seen. Otherwise |
| 3840 // use a generic IC. | 3868 // use a generic IC. |
| 3841 if (count == types->length() && FLAG_deoptimize_uncommon_cases) { | 3869 if (count == types->length() && FLAG_deoptimize_uncommon_cases) { |
| 3842 current_block()->FinishExitWithDeoptimization(); | 3870 current_block()->FinishExitWithDeoptimization(); |
| 3843 } else { | 3871 } else { |
| 3844 HContext* context = new HContext; | 3872 HContext* context = new(zone()) HContext; |
| 3845 AddInstruction(context); | 3873 AddInstruction(context); |
| 3846 HCallNamed* call = new HCallNamed(context, name, argument_count); | 3874 HCallNamed* call = new(zone()) HCallNamed(context, name, argument_count); |
| 3847 call->set_position(expr->position()); | 3875 call->set_position(expr->position()); |
| 3848 PreProcessCall(call); | 3876 PreProcessCall(call); |
| 3849 | 3877 |
| 3850 if (join != NULL) { | 3878 if (join != NULL) { |
| 3851 AddInstruction(call); | 3879 AddInstruction(call); |
| 3852 if (!ast_context()->IsEffect()) Push(call); | 3880 if (!ast_context()->IsEffect()) Push(call); |
| 3853 current_block()->Goto(join); | 3881 current_block()->Goto(join); |
| 3854 } else { | 3882 } else { |
| 3855 ast_context()->ReturnInstruction(call, expr->id()); | 3883 ast_context()->ReturnInstruction(call, expr->id()); |
| 3856 return; | 3884 return; |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3912 | 3940 |
| 3913 // No context change required. | 3941 // No context change required. |
| 3914 CompilationInfo* outer_info = info(); | 3942 CompilationInfo* outer_info = info(); |
| 3915 if (target->context() != outer_info->closure()->context() || | 3943 if (target->context() != outer_info->closure()->context() || |
| 3916 outer_info->scope()->contains_with() || | 3944 outer_info->scope()->contains_with() || |
| 3917 outer_info->scope()->num_heap_slots() > 0) { | 3945 outer_info->scope()->num_heap_slots() > 0) { |
| 3918 TraceInline(target, "target requires context change"); | 3946 TraceInline(target, "target requires context change"); |
| 3919 return false; | 3947 return false; |
| 3920 } | 3948 } |
| 3921 | 3949 |
| 3922 // Don't inline deeper than two calls. | 3950 // Don't inline deeper than kMaxInliningLevels calls. |
| 3923 HEnvironment* env = environment(); | 3951 HEnvironment* env = environment(); |
| 3924 if (env->outer() != NULL && env->outer()->outer() != NULL) { | 3952 int current_level = 1; |
| 3925 TraceInline(target, "inline depth limit reached"); | 3953 while (env->outer() != NULL) { |
| 3926 return false; | 3954 if (current_level == Compiler::kMaxInliningLevels) { |
| 3955 TraceInline(target, "inline depth limit reached"); |
| 3956 return false; |
| 3957 } |
| 3958 current_level++; |
| 3959 env = env->outer(); |
| 3927 } | 3960 } |
| 3928 | 3961 |
| 3929 // Don't inline recursive functions. | 3962 // Don't inline recursive functions. |
| 3930 if (target->shared() == outer_info->closure()->shared()) { | 3963 if (target->shared() == outer_info->closure()->shared()) { |
| 3931 TraceInline(target, "target is recursive"); | 3964 TraceInline(target, "target is recursive"); |
| 3932 return false; | 3965 return false; |
| 3933 } | 3966 } |
| 3934 | 3967 |
| 3935 // We don't want to add more than a certain number of nodes from inlining. | 3968 // We don't want to add more than a certain number of nodes from inlining. |
| 3936 if (FLAG_limit_inlining && inlined_count_ > kMaxInlinedNodes) { | 3969 if (FLAG_limit_inlining && inlined_count_ > kMaxInlinedNodes) { |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4018 FunctionState target_state(this, &target_info, &target_oracle); | 4051 FunctionState target_state(this, &target_info, &target_oracle); |
| 4019 | 4052 |
| 4020 HConstant* undefined = graph()->GetConstantUndefined(); | 4053 HConstant* undefined = graph()->GetConstantUndefined(); |
| 4021 HEnvironment* inner_env = | 4054 HEnvironment* inner_env = |
| 4022 environment()->CopyForInlining(target, function, true, undefined); | 4055 environment()->CopyForInlining(target, function, true, undefined); |
| 4023 HBasicBlock* body_entry = CreateBasicBlock(inner_env); | 4056 HBasicBlock* body_entry = CreateBasicBlock(inner_env); |
| 4024 current_block()->Goto(body_entry); | 4057 current_block()->Goto(body_entry); |
| 4025 | 4058 |
| 4026 body_entry->SetJoinId(expr->ReturnId()); | 4059 body_entry->SetJoinId(expr->ReturnId()); |
| 4027 set_current_block(body_entry); | 4060 set_current_block(body_entry); |
| 4028 AddInstruction(new HEnterInlined(target, function)); | 4061 AddInstruction(new(zone()) HEnterInlined(target, function)); |
| 4029 VisitStatements(function->body()); | 4062 VisitStatements(function->body()); |
| 4030 if (HasStackOverflow()) { | 4063 if (HasStackOverflow()) { |
| 4031 // Bail out if the inline function did, as we cannot residualize a call | 4064 // Bail out if the inline function did, as we cannot residualize a call |
| 4032 // instead. | 4065 // instead. |
| 4033 TraceInline(target, "inline graph construction failed"); | 4066 TraceInline(target, "inline graph construction failed"); |
| 4034 return false; | 4067 return false; |
| 4035 } | 4068 } |
| 4036 | 4069 |
| 4037 // Update inlined nodes count. | 4070 // Update inlined nodes count. |
| 4038 inlined_count_ += nodes_added; | 4071 inlined_count_ += nodes_added; |
| (...skipping 12 matching lines...) Expand all Loading... |
| 4051 current_block()->AddLeaveInlined(undefined, function_return()); | 4084 current_block()->AddLeaveInlined(undefined, function_return()); |
| 4052 } | 4085 } |
| 4053 } else { | 4086 } else { |
| 4054 // The graph builder assumes control can reach both branches of a | 4087 // The graph builder assumes control can reach both branches of a |
| 4055 // test, so we materialize the undefined value and test it rather than | 4088 // test, so we materialize the undefined value and test it rather than |
| 4056 // simply jumping to the false target. | 4089 // simply jumping to the false target. |
| 4057 // | 4090 // |
| 4058 // TODO(3168478): refactor to avoid this. | 4091 // TODO(3168478): refactor to avoid this. |
| 4059 HBasicBlock* empty_true = graph()->CreateBasicBlock(); | 4092 HBasicBlock* empty_true = graph()->CreateBasicBlock(); |
| 4060 HBasicBlock* empty_false = graph()->CreateBasicBlock(); | 4093 HBasicBlock* empty_false = graph()->CreateBasicBlock(); |
| 4061 HTest* test = new HTest(undefined, empty_true, empty_false); | 4094 HTest* test = new(zone()) HTest(undefined, empty_true, empty_false); |
| 4062 current_block()->Finish(test); | 4095 current_block()->Finish(test); |
| 4063 | 4096 |
| 4064 empty_true->Goto(inlined_test_context()->if_true(), false); | 4097 empty_true->Goto(inlined_test_context()->if_true(), false); |
| 4065 empty_false->Goto(inlined_test_context()->if_false(), false); | 4098 empty_false->Goto(inlined_test_context()->if_false(), false); |
| 4066 } | 4099 } |
| 4067 } | 4100 } |
| 4068 | 4101 |
| 4069 // Fix up the function exits. | 4102 // Fix up the function exits. |
| 4070 if (inlined_test_context() != NULL) { | 4103 if (inlined_test_context() != NULL) { |
| 4071 HBasicBlock* if_true = inlined_test_context()->if_true(); | 4104 HBasicBlock* if_true = inlined_test_context()->if_true(); |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4105 if (!expr->target()->shared()->HasBuiltinFunctionId()) return false; | 4138 if (!expr->target()->shared()->HasBuiltinFunctionId()) return false; |
| 4106 BuiltinFunctionId id = expr->target()->shared()->builtin_function_id(); | 4139 BuiltinFunctionId id = expr->target()->shared()->builtin_function_id(); |
| 4107 int argument_count = expr->arguments()->length() + 1; // Plus receiver. | 4140 int argument_count = expr->arguments()->length() + 1; // Plus receiver. |
| 4108 switch (id) { | 4141 switch (id) { |
| 4109 case kStringCharCodeAt: | 4142 case kStringCharCodeAt: |
| 4110 case kStringCharAt: | 4143 case kStringCharAt: |
| 4111 if (argument_count == 2 && check_type == STRING_CHECK) { | 4144 if (argument_count == 2 && check_type == STRING_CHECK) { |
| 4112 HValue* index = Pop(); | 4145 HValue* index = Pop(); |
| 4113 HValue* string = Pop(); | 4146 HValue* string = Pop(); |
| 4114 ASSERT(!expr->holder().is_null()); | 4147 ASSERT(!expr->holder().is_null()); |
| 4115 AddInstruction(new HCheckPrototypeMaps( | 4148 AddInstruction(new(zone()) HCheckPrototypeMaps( |
| 4116 oracle()->GetPrototypeForPrimitiveCheck(STRING_CHECK), | 4149 oracle()->GetPrototypeForPrimitiveCheck(STRING_CHECK), |
| 4117 expr->holder())); | 4150 expr->holder())); |
| 4118 HStringCharCodeAt* char_code = BuildStringCharCodeAt(string, index); | 4151 HStringCharCodeAt* char_code = BuildStringCharCodeAt(string, index); |
| 4119 if (id == kStringCharCodeAt) { | 4152 if (id == kStringCharCodeAt) { |
| 4120 ast_context()->ReturnInstruction(char_code, expr->id()); | 4153 ast_context()->ReturnInstruction(char_code, expr->id()); |
| 4121 return true; | 4154 return true; |
| 4122 } | 4155 } |
| 4123 AddInstruction(char_code); | 4156 AddInstruction(char_code); |
| 4124 HStringCharFromCode* result = new HStringCharFromCode(char_code); | 4157 HStringCharFromCode* result = |
| 4158 new(zone()) HStringCharFromCode(char_code); |
| 4125 ast_context()->ReturnInstruction(result, expr->id()); | 4159 ast_context()->ReturnInstruction(result, expr->id()); |
| 4126 return true; | 4160 return true; |
| 4127 } | 4161 } |
| 4128 break; | 4162 break; |
| 4129 case kMathRound: | 4163 case kMathRound: |
| 4130 case kMathFloor: | 4164 case kMathFloor: |
| 4131 case kMathAbs: | 4165 case kMathAbs: |
| 4132 case kMathSqrt: | 4166 case kMathSqrt: |
| 4133 case kMathLog: | 4167 case kMathLog: |
| 4134 case kMathSin: | 4168 case kMathSin: |
| 4135 case kMathCos: | 4169 case kMathCos: |
| 4136 if (argument_count == 2 && check_type == RECEIVER_MAP_CHECK) { | 4170 if (argument_count == 2 && check_type == RECEIVER_MAP_CHECK) { |
| 4137 AddCheckConstantFunction(expr, receiver, receiver_map, true); | 4171 AddCheckConstantFunction(expr, receiver, receiver_map, true); |
| 4138 HValue* argument = Pop(); | 4172 HValue* argument = Pop(); |
| 4139 Drop(1); // Receiver. | 4173 Drop(1); // Receiver. |
| 4140 HUnaryMathOperation* op = new HUnaryMathOperation(argument, id); | 4174 HUnaryMathOperation* op = new(zone()) HUnaryMathOperation(argument, id); |
| 4141 op->set_position(expr->position()); | 4175 op->set_position(expr->position()); |
| 4142 ast_context()->ReturnInstruction(op, expr->id()); | 4176 ast_context()->ReturnInstruction(op, expr->id()); |
| 4143 return true; | 4177 return true; |
| 4144 } | 4178 } |
| 4145 break; | 4179 break; |
| 4146 case kMathPow: | 4180 case kMathPow: |
| 4147 if (argument_count == 3 && check_type == RECEIVER_MAP_CHECK) { | 4181 if (argument_count == 3 && check_type == RECEIVER_MAP_CHECK) { |
| 4148 AddCheckConstantFunction(expr, receiver, receiver_map, true); | 4182 AddCheckConstantFunction(expr, receiver, receiver_map, true); |
| 4149 HValue* right = Pop(); | 4183 HValue* right = Pop(); |
| 4150 HValue* left = Pop(); | 4184 HValue* left = Pop(); |
| 4151 Pop(); // Pop receiver. | 4185 Pop(); // Pop receiver. |
| 4152 HInstruction* result = NULL; | 4186 HInstruction* result = NULL; |
| 4153 // Use sqrt() if exponent is 0.5 or -0.5. | 4187 // Use sqrt() if exponent is 0.5 or -0.5. |
| 4154 if (right->IsConstant() && HConstant::cast(right)->HasDoubleValue()) { | 4188 if (right->IsConstant() && HConstant::cast(right)->HasDoubleValue()) { |
| 4155 double exponent = HConstant::cast(right)->DoubleValue(); | 4189 double exponent = HConstant::cast(right)->DoubleValue(); |
| 4156 if (exponent == 0.5) { | 4190 if (exponent == 0.5) { |
| 4157 result = new HUnaryMathOperation(left, kMathPowHalf); | 4191 result = new(zone()) HUnaryMathOperation(left, kMathPowHalf); |
| 4158 } else if (exponent == -0.5) { | 4192 } else if (exponent == -0.5) { |
| 4159 HConstant* double_one = | 4193 HConstant* double_one = |
| 4160 new HConstant(Handle<Object>(Smi::FromInt(1)), | 4194 new(zone()) HConstant(Handle<Object>(Smi::FromInt(1)), |
| 4161 Representation::Double()); | 4195 Representation::Double()); |
| 4162 AddInstruction(double_one); | 4196 AddInstruction(double_one); |
| 4163 HUnaryMathOperation* square_root = | 4197 HUnaryMathOperation* square_root = |
| 4164 new HUnaryMathOperation(left, kMathPowHalf); | 4198 new(zone()) HUnaryMathOperation(left, kMathPowHalf); |
| 4165 AddInstruction(square_root); | 4199 AddInstruction(square_root); |
| 4166 // MathPowHalf doesn't have side effects so there's no need for | 4200 // MathPowHalf doesn't have side effects so there's no need for |
| 4167 // an environment simulation here. | 4201 // an environment simulation here. |
| 4168 ASSERT(!square_root->HasSideEffects()); | 4202 ASSERT(!square_root->HasSideEffects()); |
| 4169 result = new HDiv(double_one, square_root); | 4203 result = new(zone()) HDiv(double_one, square_root); |
| 4170 } else if (exponent == 2.0) { | 4204 } else if (exponent == 2.0) { |
| 4171 result = new HMul(left, left); | 4205 result = new(zone()) HMul(left, left); |
| 4172 } | 4206 } |
| 4173 } else if (right->IsConstant() && | 4207 } else if (right->IsConstant() && |
| 4174 HConstant::cast(right)->HasInteger32Value() && | 4208 HConstant::cast(right)->HasInteger32Value() && |
| 4175 HConstant::cast(right)->Integer32Value() == 2) { | 4209 HConstant::cast(right)->Integer32Value() == 2) { |
| 4176 result = new HMul(left, left); | 4210 result = new(zone()) HMul(left, left); |
| 4177 } | 4211 } |
| 4178 | 4212 |
| 4179 if (result == NULL) { | 4213 if (result == NULL) { |
| 4180 result = new HPower(left, right); | 4214 result = new(zone()) HPower(left, right); |
| 4181 } | 4215 } |
| 4182 ast_context()->ReturnInstruction(result, expr->id()); | 4216 ast_context()->ReturnInstruction(result, expr->id()); |
| 4183 return true; | 4217 return true; |
| 4184 } | 4218 } |
| 4185 break; | 4219 break; |
| 4186 default: | 4220 default: |
| 4187 // Not yet supported for inlining. | 4221 // Not yet supported for inlining. |
| 4188 break; | 4222 break; |
| 4189 } | 4223 } |
| 4190 return false; | 4224 return false; |
| (...skipping 21 matching lines...) Expand all Loading... |
| 4212 if (!expr->IsMonomorphic() || | 4246 if (!expr->IsMonomorphic() || |
| 4213 expr->check_type() != RECEIVER_MAP_CHECK) return false; | 4247 expr->check_type() != RECEIVER_MAP_CHECK) return false; |
| 4214 | 4248 |
| 4215 // Found pattern f.apply(receiver, arguments). | 4249 // Found pattern f.apply(receiver, arguments). |
| 4216 VisitForValue(prop->obj()); | 4250 VisitForValue(prop->obj()); |
| 4217 if (HasStackOverflow()) return false; | 4251 if (HasStackOverflow()) return false; |
| 4218 HValue* function = Pop(); | 4252 HValue* function = Pop(); |
| 4219 VisitForValue(args->at(0)); | 4253 VisitForValue(args->at(0)); |
| 4220 if (HasStackOverflow()) return false; | 4254 if (HasStackOverflow()) return false; |
| 4221 HValue* receiver = Pop(); | 4255 HValue* receiver = Pop(); |
| 4222 HInstruction* elements = AddInstruction(new HArgumentsElements); | 4256 HInstruction* elements = AddInstruction(new(zone()) HArgumentsElements); |
| 4223 HInstruction* length = AddInstruction(new HArgumentsLength(elements)); | 4257 HInstruction* length = AddInstruction(new(zone()) HArgumentsLength(elements)); |
| 4224 AddCheckConstantFunction(expr, | 4258 AddCheckConstantFunction(expr, |
| 4225 function, | 4259 function, |
| 4226 expr->GetReceiverTypes()->first(), | 4260 expr->GetReceiverTypes()->first(), |
| 4227 true); | 4261 true); |
| 4228 HInstruction* result = | 4262 HInstruction* result = |
| 4229 new HApplyArguments(function, receiver, length, elements); | 4263 new(zone()) HApplyArguments(function, receiver, length, elements); |
| 4230 result->set_position(expr->position()); | 4264 result->set_position(expr->position()); |
| 4231 ast_context()->ReturnInstruction(result, expr->id()); | 4265 ast_context()->ReturnInstruction(result, expr->id()); |
| 4232 return true; | 4266 return true; |
| 4233 } | 4267 } |
| 4234 | 4268 |
| 4235 | 4269 |
| 4236 void HGraphBuilder::VisitCall(Call* expr) { | 4270 void HGraphBuilder::VisitCall(Call* expr) { |
| 4237 Expression* callee = expr->expression(); | 4271 Expression* callee = expr->expression(); |
| 4238 int argument_count = expr->arguments()->length() + 1; // Plus receiver. | 4272 int argument_count = expr->arguments()->length() + 1; // Plus receiver. |
| 4239 HInstruction* call = NULL; | 4273 HInstruction* call = NULL; |
| 4240 | 4274 |
| 4241 Property* prop = callee->AsProperty(); | 4275 Property* prop = callee->AsProperty(); |
| 4242 if (prop != NULL) { | 4276 if (prop != NULL) { |
| 4243 if (!prop->key()->IsPropertyName()) { | 4277 if (!prop->key()->IsPropertyName()) { |
| 4244 // Keyed function call. | 4278 // Keyed function call. |
| 4245 VISIT_FOR_VALUE(prop->obj()); | 4279 VISIT_FOR_VALUE(prop->obj()); |
| 4246 | 4280 |
| 4247 VISIT_FOR_VALUE(prop->key()); | 4281 VISIT_FOR_VALUE(prop->key()); |
| 4248 // Push receiver and key like the non-optimized code generator expects it. | 4282 // Push receiver and key like the non-optimized code generator expects it. |
| 4249 HValue* key = Pop(); | 4283 HValue* key = Pop(); |
| 4250 HValue* receiver = Pop(); | 4284 HValue* receiver = Pop(); |
| 4251 Push(key); | 4285 Push(key); |
| 4252 Push(receiver); | 4286 Push(receiver); |
| 4253 | 4287 |
| 4254 VisitExpressions(expr->arguments()); | 4288 VisitExpressions(expr->arguments()); |
| 4255 CHECK_BAILOUT; | 4289 CHECK_BAILOUT; |
| 4256 | 4290 |
| 4257 HContext* context = new HContext; | 4291 HContext* context = new(zone()) HContext; |
| 4258 AddInstruction(context); | 4292 AddInstruction(context); |
| 4259 call = PreProcessCall(new HCallKeyed(context, key, argument_count)); | 4293 call = PreProcessCall( |
| 4294 new(zone()) HCallKeyed(context, key, argument_count)); |
| 4260 call->set_position(expr->position()); | 4295 call->set_position(expr->position()); |
| 4261 Drop(1); // Key. | 4296 Drop(1); // Key. |
| 4262 ast_context()->ReturnInstruction(call, expr->id()); | 4297 ast_context()->ReturnInstruction(call, expr->id()); |
| 4263 return; | 4298 return; |
| 4264 } | 4299 } |
| 4265 | 4300 |
| 4266 // Named function call. | 4301 // Named function call. |
| 4267 expr->RecordTypeFeedback(oracle()); | 4302 expr->RecordTypeFeedback(oracle()); |
| 4268 | 4303 |
| 4269 if (TryCallApply(expr)) return; | 4304 if (TryCallApply(expr)) return; |
| (...skipping 18 matching lines...) Expand all Loading... |
| 4288 receiver_map, | 4323 receiver_map, |
| 4289 expr->check_type())) { | 4324 expr->check_type())) { |
| 4290 return; | 4325 return; |
| 4291 } | 4326 } |
| 4292 | 4327 |
| 4293 if (CallStubCompiler::HasCustomCallGenerator(*expr->target()) || | 4328 if (CallStubCompiler::HasCustomCallGenerator(*expr->target()) || |
| 4294 expr->check_type() != RECEIVER_MAP_CHECK) { | 4329 expr->check_type() != RECEIVER_MAP_CHECK) { |
| 4295 // When the target has a custom call IC generator, use the IC, | 4330 // When the target has a custom call IC generator, use the IC, |
| 4296 // because it is likely to generate better code. Also use the IC | 4331 // because it is likely to generate better code. Also use the IC |
| 4297 // when a primitive receiver check is required. | 4332 // when a primitive receiver check is required. |
| 4298 HContext* context = new HContext; | 4333 HContext* context = new(zone()) HContext; |
| 4299 AddInstruction(context); | 4334 AddInstruction(context); |
| 4300 call = PreProcessCall(new HCallNamed(context, name, argument_count)); | 4335 call = PreProcessCall( |
| 4336 new(zone()) HCallNamed(context, name, argument_count)); |
| 4301 } else { | 4337 } else { |
| 4302 AddCheckConstantFunction(expr, receiver, receiver_map, true); | 4338 AddCheckConstantFunction(expr, receiver, receiver_map, true); |
| 4303 | 4339 |
| 4304 if (TryInline(expr)) { | 4340 if (TryInline(expr)) { |
| 4305 return; | 4341 return; |
| 4306 } else { | 4342 } else { |
| 4307 // Check for bailout, as the TryInline call in the if condition above | 4343 // Check for bailout, as the TryInline call in the if condition above |
| 4308 // might return false due to bailout during hydrogen processing. | 4344 // might return false due to bailout during hydrogen processing. |
| 4309 CHECK_BAILOUT; | 4345 CHECK_BAILOUT; |
| 4310 call = PreProcessCall(new HCallConstantFunction(expr->target(), | 4346 call = PreProcessCall( |
| 4311 argument_count)); | 4347 new(zone()) HCallConstantFunction(expr->target(), |
| 4348 argument_count)); |
| 4312 } | 4349 } |
| 4313 } | 4350 } |
| 4314 } else if (types != NULL && types->length() > 1) { | 4351 } else if (types != NULL && types->length() > 1) { |
| 4315 ASSERT(expr->check_type() == RECEIVER_MAP_CHECK); | 4352 ASSERT(expr->check_type() == RECEIVER_MAP_CHECK); |
| 4316 HandlePolymorphicCallNamed(expr, receiver, types, name); | 4353 HandlePolymorphicCallNamed(expr, receiver, types, name); |
| 4317 return; | 4354 return; |
| 4318 | 4355 |
| 4319 } else { | 4356 } else { |
| 4320 HContext* context = new HContext; | 4357 HContext* context = new(zone()) HContext; |
| 4321 AddInstruction(context); | 4358 AddInstruction(context); |
| 4322 call = PreProcessCall(new HCallNamed(context, name, argument_count)); | 4359 call = PreProcessCall( |
| 4360 new(zone()) HCallNamed(context, name, argument_count)); |
| 4323 } | 4361 } |
| 4324 | 4362 |
| 4325 } else { | 4363 } else { |
| 4326 Variable* var = expr->expression()->AsVariableProxy()->AsVariable(); | 4364 Variable* var = expr->expression()->AsVariableProxy()->AsVariable(); |
| 4327 bool global_call = (var != NULL) && var->is_global() && !var->is_this(); | 4365 bool global_call = (var != NULL) && var->is_global() && !var->is_this(); |
| 4328 | 4366 |
| 4329 if (!global_call) { | 4367 if (!global_call) { |
| 4330 ++argument_count; | 4368 ++argument_count; |
| 4331 VISIT_FOR_VALUE(expr->expression()); | 4369 VISIT_FOR_VALUE(expr->expression()); |
| 4332 } | 4370 } |
| 4333 | 4371 |
| 4334 if (global_call) { | 4372 if (global_call) { |
| 4335 bool known_global_function = false; | 4373 bool known_global_function = false; |
| 4336 // If there is a global property cell for the name at compile time and | 4374 // If there is a global property cell for the name at compile time and |
| 4337 // access check is not enabled we assume that the function will not change | 4375 // access check is not enabled we assume that the function will not change |
| 4338 // and generate optimized code for calling the function. | 4376 // and generate optimized code for calling the function. |
| 4339 LookupResult lookup; | 4377 LookupResult lookup; |
| 4340 GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, false); | 4378 GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, false); |
| 4341 if (type == kUseCell && | 4379 if (type == kUseCell && |
| 4342 !info()->global_object()->IsAccessCheckNeeded()) { | 4380 !info()->global_object()->IsAccessCheckNeeded()) { |
| 4343 Handle<GlobalObject> global(info()->global_object()); | 4381 Handle<GlobalObject> global(info()->global_object()); |
| 4344 known_global_function = expr->ComputeGlobalTarget(global, &lookup); | 4382 known_global_function = expr->ComputeGlobalTarget(global, &lookup); |
| 4345 } | 4383 } |
| 4346 if (known_global_function) { | 4384 if (known_global_function) { |
| 4347 // Push the global object instead of the global receiver because | 4385 // Push the global object instead of the global receiver because |
| 4348 // code generated by the full code generator expects it. | 4386 // code generated by the full code generator expects it. |
| 4349 HContext* context = new HContext; | 4387 HContext* context = new(zone()) HContext; |
| 4350 HGlobalObject* global_object = new HGlobalObject(context); | 4388 HGlobalObject* global_object = new(zone()) HGlobalObject(context); |
| 4351 AddInstruction(context); | 4389 AddInstruction(context); |
| 4352 PushAndAdd(global_object); | 4390 PushAndAdd(global_object); |
| 4353 VisitExpressions(expr->arguments()); | 4391 VisitExpressions(expr->arguments()); |
| 4354 CHECK_BAILOUT; | 4392 CHECK_BAILOUT; |
| 4355 | 4393 |
| 4356 VISIT_FOR_VALUE(expr->expression()); | 4394 VISIT_FOR_VALUE(expr->expression()); |
| 4357 HValue* function = Pop(); | 4395 HValue* function = Pop(); |
| 4358 AddInstruction(new HCheckFunction(function, expr->target())); | 4396 AddInstruction(new(zone()) HCheckFunction(function, expr->target())); |
| 4359 | 4397 |
| 4360 // Replace the global object with the global receiver. | 4398 // Replace the global object with the global receiver. |
| 4361 HGlobalReceiver* global_receiver = new HGlobalReceiver(global_object); | 4399 HGlobalReceiver* global_receiver = |
| 4400 new(zone()) HGlobalReceiver(global_object); |
| 4362 // Index of the receiver from the top of the expression stack. | 4401 // Index of the receiver from the top of the expression stack. |
| 4363 const int receiver_index = argument_count - 1; | 4402 const int receiver_index = argument_count - 1; |
| 4364 AddInstruction(global_receiver); | 4403 AddInstruction(global_receiver); |
| 4365 ASSERT(environment()->ExpressionStackAt(receiver_index)-> | 4404 ASSERT(environment()->ExpressionStackAt(receiver_index)-> |
| 4366 IsGlobalObject()); | 4405 IsGlobalObject()); |
| 4367 environment()->SetExpressionStackAt(receiver_index, global_receiver); | 4406 environment()->SetExpressionStackAt(receiver_index, global_receiver); |
| 4368 | 4407 |
| 4369 if (TryInline(expr)) { | 4408 if (TryInline(expr)) { |
| 4370 return; | 4409 return; |
| 4371 } | 4410 } |
| 4372 // Check for bailout, as trying to inline might fail due to bailout | 4411 // Check for bailout, as trying to inline might fail due to bailout |
| 4373 // during hydrogen processing. | 4412 // during hydrogen processing. |
| 4374 CHECK_BAILOUT; | 4413 CHECK_BAILOUT; |
| 4375 | 4414 |
| 4376 call = PreProcessCall(new HCallKnownGlobal(expr->target(), | 4415 call = PreProcessCall(new(zone()) HCallKnownGlobal(expr->target(), |
| 4377 argument_count)); | 4416 argument_count)); |
| 4378 } else { | 4417 } else { |
| 4379 HContext* context = new HContext; | 4418 HContext* context = new(zone()) HContext; |
| 4380 AddInstruction(context); | 4419 AddInstruction(context); |
| 4381 PushAndAdd(new HGlobalObject(context)); | 4420 PushAndAdd(new(zone()) HGlobalObject(context)); |
| 4382 VisitExpressions(expr->arguments()); | 4421 VisitExpressions(expr->arguments()); |
| 4383 CHECK_BAILOUT; | 4422 CHECK_BAILOUT; |
| 4384 | 4423 |
| 4385 call = PreProcessCall(new HCallGlobal(context, | 4424 call = PreProcessCall(new(zone()) HCallGlobal(context, |
| 4386 var->name(), | 4425 var->name(), |
| 4387 argument_count)); | 4426 argument_count)); |
| 4388 } | 4427 } |
| 4389 | 4428 |
| 4390 } else { | 4429 } else { |
| 4391 HContext* context = new HContext; | 4430 HContext* context = new(zone()) HContext; |
| 4392 HGlobalObject* global_object = new HGlobalObject(context); | 4431 HGlobalObject* global_object = new(zone()) HGlobalObject(context); |
| 4393 AddInstruction(context); | 4432 AddInstruction(context); |
| 4394 AddInstruction(global_object); | 4433 AddInstruction(global_object); |
| 4395 PushAndAdd(new HGlobalReceiver(global_object)); | 4434 PushAndAdd(new(zone()) HGlobalReceiver(global_object)); |
| 4396 VisitExpressions(expr->arguments()); | 4435 VisitExpressions(expr->arguments()); |
| 4397 CHECK_BAILOUT; | 4436 CHECK_BAILOUT; |
| 4398 | 4437 |
| 4399 call = PreProcessCall(new HCallFunction(context, argument_count)); | 4438 call = PreProcessCall(new(zone()) HCallFunction(context, argument_count)); |
| 4400 } | 4439 } |
| 4401 } | 4440 } |
| 4402 | 4441 |
| 4403 call->set_position(expr->position()); | 4442 call->set_position(expr->position()); |
| 4404 ast_context()->ReturnInstruction(call, expr->id()); | 4443 ast_context()->ReturnInstruction(call, expr->id()); |
| 4405 } | 4444 } |
| 4406 | 4445 |
| 4407 | 4446 |
| 4408 void HGraphBuilder::VisitCallNew(CallNew* expr) { | 4447 void HGraphBuilder::VisitCallNew(CallNew* expr) { |
| 4409 // The constructor function is also used as the receiver argument to the | 4448 // The constructor function is also used as the receiver argument to the |
| 4410 // JS construct call builtin. | 4449 // JS construct call builtin. |
| 4411 VISIT_FOR_VALUE(expr->expression()); | 4450 VISIT_FOR_VALUE(expr->expression()); |
| 4412 VisitExpressions(expr->arguments()); | 4451 VisitExpressions(expr->arguments()); |
| 4413 CHECK_BAILOUT; | 4452 CHECK_BAILOUT; |
| 4414 | 4453 |
| 4415 HContext* context = new HContext; | 4454 HContext* context = new(zone()) HContext; |
| 4416 AddInstruction(context); | 4455 AddInstruction(context); |
| 4417 | 4456 |
| 4418 // The constructor is both an operand to the instruction and an argument | 4457 // The constructor is both an operand to the instruction and an argument |
| 4419 // to the construct call. | 4458 // to the construct call. |
| 4420 int arg_count = expr->arguments()->length() + 1; // Plus constructor. | 4459 int arg_count = expr->arguments()->length() + 1; // Plus constructor. |
| 4421 HValue* constructor = environment()->ExpressionStackAt(arg_count - 1); | 4460 HValue* constructor = environment()->ExpressionStackAt(arg_count - 1); |
| 4422 HCallNew* call = new HCallNew(context, constructor, arg_count); | 4461 HCallNew* call = new(zone()) HCallNew(context, constructor, arg_count); |
| 4423 call->set_position(expr->position()); | 4462 call->set_position(expr->position()); |
| 4424 PreProcessCall(call); | 4463 PreProcessCall(call); |
| 4425 ast_context()->ReturnInstruction(call, expr->id()); | 4464 ast_context()->ReturnInstruction(call, expr->id()); |
| 4426 } | 4465 } |
| 4427 | 4466 |
| 4428 | 4467 |
| 4429 // Support for generating inlined runtime functions. | 4468 // Support for generating inlined runtime functions. |
| 4430 | 4469 |
| 4431 // Lookup table for generators for runtime calls that are generated inline. | 4470 // Lookup table for generators for runtime calls that are generated inline. |
| 4432 // Elements of the table are member pointers to functions of HGraphBuilder. | 4471 // Elements of the table are member pointers to functions of HGraphBuilder. |
| (...skipping 28 matching lines...) Expand all Loading... |
| 4461 | 4500 |
| 4462 // Call the inline code generator using the pointer-to-member. | 4501 // Call the inline code generator using the pointer-to-member. |
| 4463 (this->*generator)(expr); | 4502 (this->*generator)(expr); |
| 4464 } else { | 4503 } else { |
| 4465 ASSERT(function->intrinsic_type == Runtime::RUNTIME); | 4504 ASSERT(function->intrinsic_type == Runtime::RUNTIME); |
| 4466 VisitArgumentList(expr->arguments()); | 4505 VisitArgumentList(expr->arguments()); |
| 4467 CHECK_BAILOUT; | 4506 CHECK_BAILOUT; |
| 4468 | 4507 |
| 4469 Handle<String> name = expr->name(); | 4508 Handle<String> name = expr->name(); |
| 4470 int argument_count = expr->arguments()->length(); | 4509 int argument_count = expr->arguments()->length(); |
| 4471 HCallRuntime* call = new HCallRuntime(name, function, argument_count); | 4510 HCallRuntime* call = |
| 4511 new(zone()) HCallRuntime(name, function, argument_count); |
| 4472 call->set_position(RelocInfo::kNoPosition); | 4512 call->set_position(RelocInfo::kNoPosition); |
| 4473 Drop(argument_count); | 4513 Drop(argument_count); |
| 4474 ast_context()->ReturnInstruction(call, expr->id()); | 4514 ast_context()->ReturnInstruction(call, expr->id()); |
| 4475 } | 4515 } |
| 4476 } | 4516 } |
| 4477 | 4517 |
| 4478 | 4518 |
| 4479 void HGraphBuilder::VisitUnaryOperation(UnaryOperation* expr) { | 4519 void HGraphBuilder::VisitUnaryOperation(UnaryOperation* expr) { |
| 4480 Token::Value op = expr->op(); | 4520 Token::Value op = expr->op(); |
| 4481 if (op == Token::VOID) { | 4521 if (op == Token::VOID) { |
| (...skipping 17 matching lines...) Expand all Loading... |
| 4499 } else if (prop != NULL) { | 4539 } else if (prop != NULL) { |
| 4500 if (prop->is_synthetic()) { | 4540 if (prop->is_synthetic()) { |
| 4501 // Result of deleting parameters is false, even when they rewrite | 4541 // Result of deleting parameters is false, even when they rewrite |
| 4502 // to accesses on the arguments object. | 4542 // to accesses on the arguments object. |
| 4503 ast_context()->ReturnValue(graph()->GetConstantFalse()); | 4543 ast_context()->ReturnValue(graph()->GetConstantFalse()); |
| 4504 } else { | 4544 } else { |
| 4505 VISIT_FOR_VALUE(prop->obj()); | 4545 VISIT_FOR_VALUE(prop->obj()); |
| 4506 VISIT_FOR_VALUE(prop->key()); | 4546 VISIT_FOR_VALUE(prop->key()); |
| 4507 HValue* key = Pop(); | 4547 HValue* key = Pop(); |
| 4508 HValue* obj = Pop(); | 4548 HValue* obj = Pop(); |
| 4509 HDeleteProperty* instr = new HDeleteProperty(obj, key); | 4549 HDeleteProperty* instr = new(zone()) HDeleteProperty(obj, key); |
| 4510 ast_context()->ReturnInstruction(instr, expr->id()); | 4550 ast_context()->ReturnInstruction(instr, expr->id()); |
| 4511 } | 4551 } |
| 4512 } else if (var->is_global()) { | 4552 } else if (var->is_global()) { |
| 4513 BAILOUT("delete with global variable"); | 4553 BAILOUT("delete with global variable"); |
| 4514 } else { | 4554 } else { |
| 4515 BAILOUT("delete with non-global variable"); | 4555 BAILOUT("delete with non-global variable"); |
| 4516 } | 4556 } |
| 4517 } else if (op == Token::NOT) { | 4557 } else if (op == Token::NOT) { |
| 4518 if (ast_context()->IsTest()) { | 4558 if (ast_context()->IsTest()) { |
| 4519 TestContext* context = TestContext::cast(ast_context()); | 4559 TestContext* context = TestContext::cast(ast_context()); |
| (...skipping 20 matching lines...) Expand all Loading... |
| 4540 ast_context()->ReturnValue(Pop()); | 4580 ast_context()->ReturnValue(Pop()); |
| 4541 } else { | 4581 } else { |
| 4542 ASSERT(ast_context()->IsEffect()); | 4582 ASSERT(ast_context()->IsEffect()); |
| 4543 VisitForEffect(expr->expression()); | 4583 VisitForEffect(expr->expression()); |
| 4544 } | 4584 } |
| 4545 | 4585 |
| 4546 } else if (op == Token::TYPEOF) { | 4586 } else if (op == Token::TYPEOF) { |
| 4547 VisitForTypeOf(expr->expression()); | 4587 VisitForTypeOf(expr->expression()); |
| 4548 if (HasStackOverflow()) return; | 4588 if (HasStackOverflow()) return; |
| 4549 HValue* value = Pop(); | 4589 HValue* value = Pop(); |
| 4550 ast_context()->ReturnInstruction(new HTypeof(value), expr->id()); | 4590 ast_context()->ReturnInstruction(new(zone()) HTypeof(value), expr->id()); |
| 4551 | 4591 |
| 4552 } else { | 4592 } else { |
| 4553 VISIT_FOR_VALUE(expr->expression()); | 4593 VISIT_FOR_VALUE(expr->expression()); |
| 4554 HValue* value = Pop(); | 4594 HValue* value = Pop(); |
| 4555 HInstruction* instr = NULL; | 4595 HInstruction* instr = NULL; |
| 4556 switch (op) { | 4596 switch (op) { |
| 4557 case Token::BIT_NOT: | 4597 case Token::BIT_NOT: |
| 4558 instr = new HBitNot(value); | 4598 instr = new(zone()) HBitNot(value); |
| 4559 break; | 4599 break; |
| 4560 case Token::SUB: | 4600 case Token::SUB: |
| 4561 instr = new HMul(value, graph_->GetConstantMinus1()); | 4601 instr = new(zone()) HMul(value, graph_->GetConstantMinus1()); |
| 4562 break; | 4602 break; |
| 4563 case Token::ADD: | 4603 case Token::ADD: |
| 4564 instr = new HMul(value, graph_->GetConstant1()); | 4604 instr = new(zone()) HMul(value, graph_->GetConstant1()); |
| 4565 break; | 4605 break; |
| 4566 default: | 4606 default: |
| 4567 BAILOUT("Value: unsupported unary operation"); | 4607 BAILOUT("Value: unsupported unary operation"); |
| 4568 break; | 4608 break; |
| 4569 } | 4609 } |
| 4570 ast_context()->ReturnInstruction(instr, expr->id()); | 4610 ast_context()->ReturnInstruction(instr, expr->id()); |
| 4571 } | 4611 } |
| 4572 } | 4612 } |
| 4573 | 4613 |
| 4574 | 4614 |
| 4575 void HGraphBuilder::VisitIncrementOperation(IncrementOperation* expr) { | 4615 void HGraphBuilder::VisitIncrementOperation(IncrementOperation* expr) { |
| 4576 // IncrementOperation is never visited by the visitor. It only | 4616 // IncrementOperation is never visited by the visitor. It only |
| 4577 // occurs as a subexpression of CountOperation. | 4617 // occurs as a subexpression of CountOperation. |
| 4578 UNREACHABLE(); | 4618 UNREACHABLE(); |
| 4579 } | 4619 } |
| 4580 | 4620 |
| 4581 | 4621 |
| 4582 HInstruction* HGraphBuilder::BuildIncrement(HValue* value, bool increment) { | 4622 HInstruction* HGraphBuilder::BuildIncrement(HValue* value, bool increment) { |
| 4583 HConstant* delta = increment | 4623 HConstant* delta = increment |
| 4584 ? graph_->GetConstant1() | 4624 ? graph_->GetConstant1() |
| 4585 : graph_->GetConstantMinus1(); | 4625 : graph_->GetConstantMinus1(); |
| 4586 HInstruction* instr = new HAdd(value, delta); | 4626 HInstruction* instr = new(zone()) HAdd(value, delta); |
| 4587 AssumeRepresentation(instr, Representation::Integer32()); | 4627 AssumeRepresentation(instr, Representation::Integer32()); |
| 4588 return instr; | 4628 return instr; |
| 4589 } | 4629 } |
| 4590 | 4630 |
| 4591 | 4631 |
| 4592 void HGraphBuilder::VisitCountOperation(CountOperation* expr) { | 4632 void HGraphBuilder::VisitCountOperation(CountOperation* expr) { |
| 4593 IncrementOperation* increment = expr->increment(); | 4633 IncrementOperation* increment = expr->increment(); |
| 4594 Expression* target = increment->expression(); | 4634 Expression* target = increment->expression(); |
| 4595 VariableProxy* proxy = target->AsVariableProxy(); | 4635 VariableProxy* proxy = target->AsVariableProxy(); |
| 4596 Variable* var = proxy->AsVariable(); | 4636 Variable* var = proxy->AsVariable(); |
| (...skipping 15 matching lines...) Expand all Loading... |
| 4612 if (var->is_global()) { | 4652 if (var->is_global()) { |
| 4613 HandleGlobalVariableAssignment(var, | 4653 HandleGlobalVariableAssignment(var, |
| 4614 after, | 4654 after, |
| 4615 expr->position(), | 4655 expr->position(), |
| 4616 expr->AssignmentId()); | 4656 expr->AssignmentId()); |
| 4617 } else if (var->IsStackAllocated()) { | 4657 } else if (var->IsStackAllocated()) { |
| 4618 Bind(var, after); | 4658 Bind(var, after); |
| 4619 } else if (var->IsContextSlot()) { | 4659 } else if (var->IsContextSlot()) { |
| 4620 HValue* context = BuildContextChainWalk(var); | 4660 HValue* context = BuildContextChainWalk(var); |
| 4621 int index = var->AsSlot()->index(); | 4661 int index = var->AsSlot()->index(); |
| 4622 HStoreContextSlot* instr = new HStoreContextSlot(context, index, after); | 4662 HStoreContextSlot* instr = |
| 4663 new(zone()) HStoreContextSlot(context, index, after); |
| 4623 AddInstruction(instr); | 4664 AddInstruction(instr); |
| 4624 if (instr->HasSideEffects()) AddSimulate(expr->AssignmentId()); | 4665 if (instr->HasSideEffects()) AddSimulate(expr->AssignmentId()); |
| 4625 } else { | 4666 } else { |
| 4626 BAILOUT("lookup variable in count operation"); | 4667 BAILOUT("lookup variable in count operation"); |
| 4627 } | 4668 } |
| 4628 Drop(has_extra ? 2 : 1); | 4669 Drop(has_extra ? 2 : 1); |
| 4629 ast_context()->ReturnValue(expr->is_postfix() ? before : after); | 4670 ast_context()->ReturnValue(expr->is_postfix() ? before : after); |
| 4630 | 4671 |
| 4631 } else if (prop != NULL) { | 4672 } else if (prop != NULL) { |
| 4632 prop->RecordTypeFeedback(oracle()); | 4673 prop->RecordTypeFeedback(oracle()); |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4718 } | 4759 } |
| 4719 | 4760 |
| 4720 } else { | 4761 } else { |
| 4721 BAILOUT("invalid lhs in count operation"); | 4762 BAILOUT("invalid lhs in count operation"); |
| 4722 } | 4763 } |
| 4723 } | 4764 } |
| 4724 | 4765 |
| 4725 | 4766 |
| 4726 HStringCharCodeAt* HGraphBuilder::BuildStringCharCodeAt(HValue* string, | 4767 HStringCharCodeAt* HGraphBuilder::BuildStringCharCodeAt(HValue* string, |
| 4727 HValue* index) { | 4768 HValue* index) { |
| 4728 AddInstruction(new HCheckNonSmi(string)); | 4769 AddInstruction(new(zone()) HCheckNonSmi(string)); |
| 4729 AddInstruction(new HCheckInstanceType( | 4770 AddInstruction(new(zone()) HCheckInstanceType( |
| 4730 string, FIRST_STRING_TYPE, LAST_STRING_TYPE)); | 4771 string, FIRST_STRING_TYPE, LAST_STRING_TYPE)); |
| 4731 HStringLength* length = new HStringLength(string); | 4772 HStringLength* length = new(zone()) HStringLength(string); |
| 4732 AddInstruction(length); | 4773 AddInstruction(length); |
| 4733 AddInstruction(new HBoundsCheck(index, length)); | 4774 AddInstruction(new(zone()) HBoundsCheck(index, length)); |
| 4734 return new HStringCharCodeAt(string, index); | 4775 return new(zone()) HStringCharCodeAt(string, index); |
| 4735 } | 4776 } |
| 4736 | 4777 |
| 4737 | 4778 |
| 4738 HInstruction* HGraphBuilder::BuildBinaryOperation(BinaryOperation* expr, | 4779 HInstruction* HGraphBuilder::BuildBinaryOperation(BinaryOperation* expr, |
| 4739 HValue* left, | 4780 HValue* left, |
| 4740 HValue* right) { | 4781 HValue* right) { |
| 4741 HInstruction* instr = NULL; | 4782 HInstruction* instr = NULL; |
| 4742 switch (expr->op()) { | 4783 switch (expr->op()) { |
| 4743 case Token::ADD: | 4784 case Token::ADD: |
| 4744 instr = new HAdd(left, right); | 4785 instr = new(zone()) HAdd(left, right); |
| 4745 break; | 4786 break; |
| 4746 case Token::SUB: | 4787 case Token::SUB: |
| 4747 instr = new HSub(left, right); | 4788 instr = new(zone()) HSub(left, right); |
| 4748 break; | 4789 break; |
| 4749 case Token::MUL: | 4790 case Token::MUL: |
| 4750 instr = new HMul(left, right); | 4791 instr = new(zone()) HMul(left, right); |
| 4751 break; | 4792 break; |
| 4752 case Token::MOD: | 4793 case Token::MOD: |
| 4753 instr = new HMod(left, right); | 4794 instr = new(zone()) HMod(left, right); |
| 4754 break; | 4795 break; |
| 4755 case Token::DIV: | 4796 case Token::DIV: |
| 4756 instr = new HDiv(left, right); | 4797 instr = new(zone()) HDiv(left, right); |
| 4757 break; | 4798 break; |
| 4758 case Token::BIT_XOR: | 4799 case Token::BIT_XOR: |
| 4759 instr = new HBitXor(left, right); | 4800 instr = new(zone()) HBitXor(left, right); |
| 4760 break; | 4801 break; |
| 4761 case Token::BIT_AND: | 4802 case Token::BIT_AND: |
| 4762 instr = new HBitAnd(left, right); | 4803 instr = new(zone()) HBitAnd(left, right); |
| 4763 break; | 4804 break; |
| 4764 case Token::BIT_OR: | 4805 case Token::BIT_OR: |
| 4765 instr = new HBitOr(left, right); | 4806 instr = new(zone()) HBitOr(left, right); |
| 4766 break; | 4807 break; |
| 4767 case Token::SAR: | 4808 case Token::SAR: |
| 4768 instr = new HSar(left, right); | 4809 instr = new(zone()) HSar(left, right); |
| 4769 break; | 4810 break; |
| 4770 case Token::SHR: | 4811 case Token::SHR: |
| 4771 instr = new HShr(left, right); | 4812 instr = new(zone()) HShr(left, right); |
| 4772 break; | 4813 break; |
| 4773 case Token::SHL: | 4814 case Token::SHL: |
| 4774 instr = new HShl(left, right); | 4815 instr = new(zone()) HShl(left, right); |
| 4775 break; | 4816 break; |
| 4776 default: | 4817 default: |
| 4777 UNREACHABLE(); | 4818 UNREACHABLE(); |
| 4778 } | 4819 } |
| 4779 TypeInfo info = oracle()->BinaryType(expr); | 4820 TypeInfo info = oracle()->BinaryType(expr); |
| 4780 // If we hit an uninitialized binary op stub we will get type info | 4821 // If we hit an uninitialized binary op stub we will get type info |
| 4781 // for a smi operation. If one of the operands is a constant string | 4822 // for a smi operation. If one of the operands is a constant string |
| 4782 // do not generate code assuming it is a smi operation. | 4823 // do not generate code assuming it is a smi operation. |
| 4783 if (info.IsSmi() && | 4824 if (info.IsSmi() && |
| 4784 ((left->IsConstant() && HConstant::cast(left)->HasStringValue()) || | 4825 ((left->IsConstant() && HConstant::cast(left)->HasStringValue()) || |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4838 Visit(expr->right()); | 4879 Visit(expr->right()); |
| 4839 | 4880 |
| 4840 } else if (ast_context()->IsValue()) { | 4881 } else if (ast_context()->IsValue()) { |
| 4841 VISIT_FOR_VALUE(expr->left()); | 4882 VISIT_FOR_VALUE(expr->left()); |
| 4842 ASSERT(current_block() != NULL); | 4883 ASSERT(current_block() != NULL); |
| 4843 | 4884 |
| 4844 // We need an extra block to maintain edge-split form. | 4885 // We need an extra block to maintain edge-split form. |
| 4845 HBasicBlock* empty_block = graph()->CreateBasicBlock(); | 4886 HBasicBlock* empty_block = graph()->CreateBasicBlock(); |
| 4846 HBasicBlock* eval_right = graph()->CreateBasicBlock(); | 4887 HBasicBlock* eval_right = graph()->CreateBasicBlock(); |
| 4847 HTest* test = is_logical_and | 4888 HTest* test = is_logical_and |
| 4848 ? new HTest(Top(), eval_right, empty_block) | 4889 ? new(zone()) HTest(Top(), eval_right, empty_block) |
| 4849 : new HTest(Top(), empty_block, eval_right); | 4890 : new(zone()) HTest(Top(), empty_block, eval_right); |
| 4850 current_block()->Finish(test); | 4891 current_block()->Finish(test); |
| 4851 | 4892 |
| 4852 set_current_block(eval_right); | 4893 set_current_block(eval_right); |
| 4853 Drop(1); // Value of the left subexpression. | 4894 Drop(1); // Value of the left subexpression. |
| 4854 VISIT_FOR_VALUE(expr->right()); | 4895 VISIT_FOR_VALUE(expr->right()); |
| 4855 | 4896 |
| 4856 HBasicBlock* join_block = | 4897 HBasicBlock* join_block = |
| 4857 CreateJoin(empty_block, current_block(), expr->id()); | 4898 CreateJoin(empty_block, current_block(), expr->id()); |
| 4858 set_current_block(join_block); | 4899 set_current_block(join_block); |
| 4859 ast_context()->ReturnValue(Pop()); | 4900 ast_context()->ReturnValue(Pop()); |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4929 } | 4970 } |
| 4930 | 4971 |
| 4931 | 4972 |
| 4932 void HGraphBuilder::VisitCompareOperation(CompareOperation* expr) { | 4973 void HGraphBuilder::VisitCompareOperation(CompareOperation* expr) { |
| 4933 if (IsClassOfTest(expr)) { | 4974 if (IsClassOfTest(expr)) { |
| 4934 CallRuntime* call = expr->left()->AsCallRuntime(); | 4975 CallRuntime* call = expr->left()->AsCallRuntime(); |
| 4935 VISIT_FOR_VALUE(call->arguments()->at(0)); | 4976 VISIT_FOR_VALUE(call->arguments()->at(0)); |
| 4936 HValue* value = Pop(); | 4977 HValue* value = Pop(); |
| 4937 Literal* literal = expr->right()->AsLiteral(); | 4978 Literal* literal = expr->right()->AsLiteral(); |
| 4938 Handle<String> rhs = Handle<String>::cast(literal->handle()); | 4979 Handle<String> rhs = Handle<String>::cast(literal->handle()); |
| 4939 HInstruction* instr = new HClassOfTest(value, rhs); | 4980 HInstruction* instr = new(zone()) HClassOfTest(value, rhs); |
| 4940 instr->set_position(expr->position()); | 4981 instr->set_position(expr->position()); |
| 4941 ast_context()->ReturnInstruction(instr, expr->id()); | 4982 ast_context()->ReturnInstruction(instr, expr->id()); |
| 4942 return; | 4983 return; |
| 4943 } | 4984 } |
| 4944 | 4985 |
| 4945 // Check for the pattern: typeof <expression> == <string literal>. | 4986 // Check for the pattern: typeof <expression> == <string literal>. |
| 4946 UnaryOperation* left_unary = expr->left()->AsUnaryOperation(); | 4987 UnaryOperation* left_unary = expr->left()->AsUnaryOperation(); |
| 4947 Literal* right_literal = expr->right()->AsLiteral(); | 4988 Literal* right_literal = expr->right()->AsLiteral(); |
| 4948 if ((expr->op() == Token::EQ || expr->op() == Token::EQ_STRICT) && | 4989 if ((expr->op() == Token::EQ || expr->op() == Token::EQ_STRICT) && |
| 4949 left_unary != NULL && left_unary->op() == Token::TYPEOF && | 4990 left_unary != NULL && left_unary->op() == Token::TYPEOF && |
| 4950 right_literal != NULL && right_literal->handle()->IsString()) { | 4991 right_literal != NULL && right_literal->handle()->IsString()) { |
| 4951 VisitForTypeOf(left_unary->expression()); | 4992 VisitForTypeOf(left_unary->expression()); |
| 4952 if (HasStackOverflow()) return; | 4993 if (HasStackOverflow()) return; |
| 4953 HValue* left = Pop(); | 4994 HValue* left = Pop(); |
| 4954 HInstruction* instr = new HTypeofIs(left, | 4995 HInstruction* instr = new(zone()) HTypeofIs(left, |
| 4955 Handle<String>::cast(right_literal->handle())); | 4996 Handle<String>::cast(right_literal->handle())); |
| 4956 instr->set_position(expr->position()); | 4997 instr->set_position(expr->position()); |
| 4957 ast_context()->ReturnInstruction(instr, expr->id()); | 4998 ast_context()->ReturnInstruction(instr, expr->id()); |
| 4958 return; | 4999 return; |
| 4959 } | 5000 } |
| 4960 | 5001 |
| 4961 VISIT_FOR_VALUE(expr->left()); | 5002 VISIT_FOR_VALUE(expr->left()); |
| 4962 VISIT_FOR_VALUE(expr->right()); | 5003 VISIT_FOR_VALUE(expr->right()); |
| 4963 | 5004 |
| 4964 HValue* right = Pop(); | 5005 HValue* right = Pop(); |
| (...skipping 24 matching lines...) Expand all Loading... |
| 4989 // change and thus prefer the general IC code. | 5030 // change and thus prefer the general IC code. |
| 4990 if (!isolate()->heap()->InNewSpace(*candidate)) { | 5031 if (!isolate()->heap()->InNewSpace(*candidate)) { |
| 4991 target = candidate; | 5032 target = candidate; |
| 4992 } | 5033 } |
| 4993 } | 5034 } |
| 4994 } | 5035 } |
| 4995 | 5036 |
| 4996 // If the target is not null we have found a known global function that is | 5037 // If the target is not null we have found a known global function that is |
| 4997 // assumed to stay the same for this instanceof. | 5038 // assumed to stay the same for this instanceof. |
| 4998 if (target.is_null()) { | 5039 if (target.is_null()) { |
| 4999 HContext* context = new HContext; | 5040 HContext* context = new(zone()) HContext; |
| 5000 AddInstruction(context); | 5041 AddInstruction(context); |
| 5001 instr = new HInstanceOf(context, left, right); | 5042 instr = new(zone()) HInstanceOf(context, left, right); |
| 5002 } else { | 5043 } else { |
| 5003 AddInstruction(new HCheckFunction(right, target)); | 5044 AddInstruction(new(zone()) HCheckFunction(right, target)); |
| 5004 instr = new HInstanceOfKnownGlobal(left, target); | 5045 instr = new(zone()) HInstanceOfKnownGlobal(left, target); |
| 5005 } | 5046 } |
| 5006 } else if (op == Token::IN) { | 5047 } else if (op == Token::IN) { |
| 5007 BAILOUT("Unsupported comparison: in"); | 5048 BAILOUT("Unsupported comparison: in"); |
| 5008 } else if (type_info.IsNonPrimitive()) { | 5049 } else if (type_info.IsNonPrimitive()) { |
| 5009 switch (op) { | 5050 switch (op) { |
| 5010 case Token::EQ: | 5051 case Token::EQ: |
| 5011 case Token::EQ_STRICT: { | 5052 case Token::EQ_STRICT: { |
| 5012 AddInstruction(new HCheckNonSmi(left)); | 5053 AddInstruction(new(zone()) HCheckNonSmi(left)); |
| 5013 AddInstruction(HCheckInstanceType::NewIsJSObjectOrJSFunction(left)); | 5054 AddInstruction(HCheckInstanceType::NewIsJSObjectOrJSFunction(left)); |
| 5014 AddInstruction(new HCheckNonSmi(right)); | 5055 AddInstruction(new(zone()) HCheckNonSmi(right)); |
| 5015 AddInstruction(HCheckInstanceType::NewIsJSObjectOrJSFunction(right)); | 5056 AddInstruction(HCheckInstanceType::NewIsJSObjectOrJSFunction(right)); |
| 5016 instr = new HCompareJSObjectEq(left, right); | 5057 instr = new(zone()) HCompareJSObjectEq(left, right); |
| 5017 break; | 5058 break; |
| 5018 } | 5059 } |
| 5019 default: | 5060 default: |
| 5020 BAILOUT("Unsupported non-primitive compare"); | 5061 BAILOUT("Unsupported non-primitive compare"); |
| 5021 break; | 5062 break; |
| 5022 } | 5063 } |
| 5023 } else { | 5064 } else { |
| 5024 HCompare* compare = new HCompare(left, right, op); | 5065 HCompare* compare = new(zone()) HCompare(left, right, op); |
| 5025 Representation r = ToRepresentation(type_info); | 5066 Representation r = ToRepresentation(type_info); |
| 5026 compare->SetInputRepresentation(r); | 5067 compare->SetInputRepresentation(r); |
| 5027 instr = compare; | 5068 instr = compare; |
| 5028 } | 5069 } |
| 5029 instr->set_position(expr->position()); | 5070 instr->set_position(expr->position()); |
| 5030 ast_context()->ReturnInstruction(instr, expr->id()); | 5071 ast_context()->ReturnInstruction(instr, expr->id()); |
| 5031 } | 5072 } |
| 5032 | 5073 |
| 5033 | 5074 |
| 5034 void HGraphBuilder::VisitCompareToNull(CompareToNull* expr) { | 5075 void HGraphBuilder::VisitCompareToNull(CompareToNull* expr) { |
| 5035 VISIT_FOR_VALUE(expr->expression()); | 5076 VISIT_FOR_VALUE(expr->expression()); |
| 5036 | 5077 |
| 5037 HValue* value = Pop(); | 5078 HValue* value = Pop(); |
| 5038 HIsNull* compare = new HIsNull(value, expr->is_strict()); | 5079 HIsNull* compare = new(zone()) HIsNull(value, expr->is_strict()); |
| 5039 ast_context()->ReturnInstruction(compare, expr->id()); | 5080 ast_context()->ReturnInstruction(compare, expr->id()); |
| 5040 } | 5081 } |
| 5041 | 5082 |
| 5042 | 5083 |
| 5043 void HGraphBuilder::VisitThisFunction(ThisFunction* expr) { | 5084 void HGraphBuilder::VisitThisFunction(ThisFunction* expr) { |
| 5044 BAILOUT("ThisFunction"); | 5085 BAILOUT("ThisFunction"); |
| 5045 } | 5086 } |
| 5046 | 5087 |
| 5047 | 5088 |
| 5048 void HGraphBuilder::VisitDeclaration(Declaration* decl) { | 5089 void HGraphBuilder::VisitDeclaration(Declaration* decl) { |
| (...skipping 11 matching lines...) Expand all Loading... |
| 5060 } | 5101 } |
| 5061 } | 5102 } |
| 5062 | 5103 |
| 5063 | 5104 |
| 5064 // Generators for inline runtime functions. | 5105 // Generators for inline runtime functions. |
| 5065 // Support for types. | 5106 // Support for types. |
| 5066 void HGraphBuilder::GenerateIsSmi(CallRuntime* call) { | 5107 void HGraphBuilder::GenerateIsSmi(CallRuntime* call) { |
| 5067 ASSERT(call->arguments()->length() == 1); | 5108 ASSERT(call->arguments()->length() == 1); |
| 5068 VISIT_FOR_VALUE(call->arguments()->at(0)); | 5109 VISIT_FOR_VALUE(call->arguments()->at(0)); |
| 5069 HValue* value = Pop(); | 5110 HValue* value = Pop(); |
| 5070 HIsSmi* result = new HIsSmi(value); | 5111 HIsSmi* result = new(zone()) HIsSmi(value); |
| 5071 ast_context()->ReturnInstruction(result, call->id()); | 5112 ast_context()->ReturnInstruction(result, call->id()); |
| 5072 } | 5113 } |
| 5073 | 5114 |
| 5074 | 5115 |
| 5075 void HGraphBuilder::GenerateIsSpecObject(CallRuntime* call) { | 5116 void HGraphBuilder::GenerateIsSpecObject(CallRuntime* call) { |
| 5076 ASSERT(call->arguments()->length() == 1); | 5117 ASSERT(call->arguments()->length() == 1); |
| 5077 VISIT_FOR_VALUE(call->arguments()->at(0)); | 5118 VISIT_FOR_VALUE(call->arguments()->at(0)); |
| 5078 HValue* value = Pop(); | 5119 HValue* value = Pop(); |
| 5079 HHasInstanceType* result = | 5120 HHasInstanceType* result = |
| 5080 new HHasInstanceType(value, FIRST_JS_OBJECT_TYPE, LAST_TYPE); | 5121 new(zone()) HHasInstanceType(value, FIRST_JS_OBJECT_TYPE, LAST_TYPE); |
| 5081 ast_context()->ReturnInstruction(result, call->id()); | 5122 ast_context()->ReturnInstruction(result, call->id()); |
| 5082 } | 5123 } |
| 5083 | 5124 |
| 5084 | 5125 |
| 5085 void HGraphBuilder::GenerateIsFunction(CallRuntime* call) { | 5126 void HGraphBuilder::GenerateIsFunction(CallRuntime* call) { |
| 5086 ASSERT(call->arguments()->length() == 1); | 5127 ASSERT(call->arguments()->length() == 1); |
| 5087 VISIT_FOR_VALUE(call->arguments()->at(0)); | 5128 VISIT_FOR_VALUE(call->arguments()->at(0)); |
| 5088 HValue* value = Pop(); | 5129 HValue* value = Pop(); |
| 5089 HHasInstanceType* result = new HHasInstanceType(value, JS_FUNCTION_TYPE); | 5130 HHasInstanceType* result = |
| 5131 new(zone()) HHasInstanceType(value, JS_FUNCTION_TYPE); |
| 5090 ast_context()->ReturnInstruction(result, call->id()); | 5132 ast_context()->ReturnInstruction(result, call->id()); |
| 5091 } | 5133 } |
| 5092 | 5134 |
| 5093 | 5135 |
| 5094 void HGraphBuilder::GenerateHasCachedArrayIndex(CallRuntime* call) { | 5136 void HGraphBuilder::GenerateHasCachedArrayIndex(CallRuntime* call) { |
| 5095 ASSERT(call->arguments()->length() == 1); | 5137 ASSERT(call->arguments()->length() == 1); |
| 5096 VISIT_FOR_VALUE(call->arguments()->at(0)); | 5138 VISIT_FOR_VALUE(call->arguments()->at(0)); |
| 5097 HValue* value = Pop(); | 5139 HValue* value = Pop(); |
| 5098 HHasCachedArrayIndex* result = new HHasCachedArrayIndex(value); | 5140 HHasCachedArrayIndex* result = new(zone()) HHasCachedArrayIndex(value); |
| 5099 ast_context()->ReturnInstruction(result, call->id()); | 5141 ast_context()->ReturnInstruction(result, call->id()); |
| 5100 } | 5142 } |
| 5101 | 5143 |
| 5102 | 5144 |
| 5103 void HGraphBuilder::GenerateIsArray(CallRuntime* call) { | 5145 void HGraphBuilder::GenerateIsArray(CallRuntime* call) { |
| 5104 ASSERT(call->arguments()->length() == 1); | 5146 ASSERT(call->arguments()->length() == 1); |
| 5105 VISIT_FOR_VALUE(call->arguments()->at(0)); | 5147 VISIT_FOR_VALUE(call->arguments()->at(0)); |
| 5106 HValue* value = Pop(); | 5148 HValue* value = Pop(); |
| 5107 HHasInstanceType* result = new HHasInstanceType(value, JS_ARRAY_TYPE); | 5149 HHasInstanceType* result = new(zone()) HHasInstanceType(value, JS_ARRAY_TYPE); |
| 5108 ast_context()->ReturnInstruction(result, call->id()); | 5150 ast_context()->ReturnInstruction(result, call->id()); |
| 5109 } | 5151 } |
| 5110 | 5152 |
| 5111 | 5153 |
| 5112 void HGraphBuilder::GenerateIsRegExp(CallRuntime* call) { | 5154 void HGraphBuilder::GenerateIsRegExp(CallRuntime* call) { |
| 5113 ASSERT(call->arguments()->length() == 1); | 5155 ASSERT(call->arguments()->length() == 1); |
| 5114 VISIT_FOR_VALUE(call->arguments()->at(0)); | 5156 VISIT_FOR_VALUE(call->arguments()->at(0)); |
| 5115 HValue* value = Pop(); | 5157 HValue* value = Pop(); |
| 5116 HHasInstanceType* result = new HHasInstanceType(value, JS_REGEXP_TYPE); | 5158 HHasInstanceType* result = |
| 5159 new(zone()) HHasInstanceType(value, JS_REGEXP_TYPE); |
| 5117 ast_context()->ReturnInstruction(result, call->id()); | 5160 ast_context()->ReturnInstruction(result, call->id()); |
| 5118 } | 5161 } |
| 5119 | 5162 |
| 5120 | 5163 |
| 5121 void HGraphBuilder::GenerateIsObject(CallRuntime* call) { | 5164 void HGraphBuilder::GenerateIsObject(CallRuntime* call) { |
| 5122 ASSERT(call->arguments()->length() == 1); | 5165 ASSERT(call->arguments()->length() == 1); |
| 5123 VISIT_FOR_VALUE(call->arguments()->at(0)); | 5166 VISIT_FOR_VALUE(call->arguments()->at(0)); |
| 5124 HValue* value = Pop(); | 5167 HValue* value = Pop(); |
| 5125 HIsObject* test = new HIsObject(value); | 5168 HIsObject* test = new(zone()) HIsObject(value); |
| 5126 ast_context()->ReturnInstruction(test, call->id()); | 5169 ast_context()->ReturnInstruction(test, call->id()); |
| 5127 } | 5170 } |
| 5128 | 5171 |
| 5129 | 5172 |
| 5130 void HGraphBuilder::GenerateIsNonNegativeSmi(CallRuntime* call) { | 5173 void HGraphBuilder::GenerateIsNonNegativeSmi(CallRuntime* call) { |
| 5131 BAILOUT("inlined runtime function: IsNonNegativeSmi"); | 5174 BAILOUT("inlined runtime function: IsNonNegativeSmi"); |
| 5132 } | 5175 } |
| 5133 | 5176 |
| 5134 | 5177 |
| 5135 void HGraphBuilder::GenerateIsUndetectableObject(CallRuntime* call) { | 5178 void HGraphBuilder::GenerateIsUndetectableObject(CallRuntime* call) { |
| 5136 BAILOUT("inlined runtime function: IsUndetectableObject"); | 5179 BAILOUT("inlined runtime function: IsUndetectableObject"); |
| 5137 } | 5180 } |
| 5138 | 5181 |
| 5139 | 5182 |
| 5140 void HGraphBuilder::GenerateIsStringWrapperSafeForDefaultValueOf( | 5183 void HGraphBuilder::GenerateIsStringWrapperSafeForDefaultValueOf( |
| 5141 CallRuntime* call) { | 5184 CallRuntime* call) { |
| 5142 BAILOUT("inlined runtime function: IsStringWrapperSafeForDefaultValueOf"); | 5185 BAILOUT("inlined runtime function: IsStringWrapperSafeForDefaultValueOf"); |
| 5143 } | 5186 } |
| 5144 | 5187 |
| 5145 | 5188 |
| 5146 // Support for construct call checks. | 5189 // Support for construct call checks. |
| 5147 void HGraphBuilder::GenerateIsConstructCall(CallRuntime* call) { | 5190 void HGraphBuilder::GenerateIsConstructCall(CallRuntime* call) { |
| 5148 ASSERT(call->arguments()->length() == 0); | 5191 ASSERT(call->arguments()->length() == 0); |
| 5149 if (function_state()->outer() != NULL) { | 5192 if (function_state()->outer() != NULL) { |
| 5150 // We are generating graph for inlined function. Currently | 5193 // We are generating graph for inlined function. Currently |
| 5151 // constructor inlining is not supported and we can just return | 5194 // constructor inlining is not supported and we can just return |
| 5152 // false from %_IsConstructCall(). | 5195 // false from %_IsConstructCall(). |
| 5153 ast_context()->ReturnValue(graph()->GetConstantFalse()); | 5196 ast_context()->ReturnValue(graph()->GetConstantFalse()); |
| 5154 } else { | 5197 } else { |
| 5155 ast_context()->ReturnInstruction(new HIsConstructCall, call->id()); | 5198 ast_context()->ReturnInstruction(new(zone()) HIsConstructCall, call->id()); |
| 5156 } | 5199 } |
| 5157 } | 5200 } |
| 5158 | 5201 |
| 5159 | 5202 |
| 5160 // Support for arguments.length and arguments[?]. | 5203 // Support for arguments.length and arguments[?]. |
| 5161 void HGraphBuilder::GenerateArgumentsLength(CallRuntime* call) { | 5204 void HGraphBuilder::GenerateArgumentsLength(CallRuntime* call) { |
| 5162 ASSERT(call->arguments()->length() == 0); | 5205 ASSERT(call->arguments()->length() == 0); |
| 5163 HInstruction* elements = AddInstruction(new HArgumentsElements); | 5206 HInstruction* elements = AddInstruction(new(zone()) HArgumentsElements); |
| 5164 HArgumentsLength* result = new HArgumentsLength(elements); | 5207 HArgumentsLength* result = new(zone()) HArgumentsLength(elements); |
| 5165 ast_context()->ReturnInstruction(result, call->id()); | 5208 ast_context()->ReturnInstruction(result, call->id()); |
| 5166 } | 5209 } |
| 5167 | 5210 |
| 5168 | 5211 |
| 5169 void HGraphBuilder::GenerateArguments(CallRuntime* call) { | 5212 void HGraphBuilder::GenerateArguments(CallRuntime* call) { |
| 5170 ASSERT(call->arguments()->length() == 1); | 5213 ASSERT(call->arguments()->length() == 1); |
| 5171 VISIT_FOR_VALUE(call->arguments()->at(0)); | 5214 VISIT_FOR_VALUE(call->arguments()->at(0)); |
| 5172 HValue* index = Pop(); | 5215 HValue* index = Pop(); |
| 5173 HInstruction* elements = AddInstruction(new HArgumentsElements); | 5216 HInstruction* elements = AddInstruction(new(zone()) HArgumentsElements); |
| 5174 HInstruction* length = AddInstruction(new HArgumentsLength(elements)); | 5217 HInstruction* length = AddInstruction(new(zone()) HArgumentsLength(elements)); |
| 5175 HAccessArgumentsAt* result = new HAccessArgumentsAt(elements, length, index); | 5218 HAccessArgumentsAt* result = |
| 5219 new(zone()) HAccessArgumentsAt(elements, length, index); |
| 5176 ast_context()->ReturnInstruction(result, call->id()); | 5220 ast_context()->ReturnInstruction(result, call->id()); |
| 5177 } | 5221 } |
| 5178 | 5222 |
| 5179 | 5223 |
| 5180 // Support for accessing the class and value fields of an object. | 5224 // Support for accessing the class and value fields of an object. |
| 5181 void HGraphBuilder::GenerateClassOf(CallRuntime* call) { | 5225 void HGraphBuilder::GenerateClassOf(CallRuntime* call) { |
| 5182 // The special form detected by IsClassOfTest is detected before we get here | 5226 // The special form detected by IsClassOfTest is detected before we get here |
| 5183 // and does not cause a bailout. | 5227 // and does not cause a bailout. |
| 5184 BAILOUT("inlined runtime function: ClassOf"); | 5228 BAILOUT("inlined runtime function: ClassOf"); |
| 5185 } | 5229 } |
| 5186 | 5230 |
| 5187 | 5231 |
| 5188 void HGraphBuilder::GenerateValueOf(CallRuntime* call) { | 5232 void HGraphBuilder::GenerateValueOf(CallRuntime* call) { |
| 5189 ASSERT(call->arguments()->length() == 1); | 5233 ASSERT(call->arguments()->length() == 1); |
| 5190 VISIT_FOR_VALUE(call->arguments()->at(0)); | 5234 VISIT_FOR_VALUE(call->arguments()->at(0)); |
| 5191 HValue* value = Pop(); | 5235 HValue* value = Pop(); |
| 5192 HValueOf* result = new HValueOf(value); | 5236 HValueOf* result = new(zone()) HValueOf(value); |
| 5193 ast_context()->ReturnInstruction(result, call->id()); | 5237 ast_context()->ReturnInstruction(result, call->id()); |
| 5194 } | 5238 } |
| 5195 | 5239 |
| 5196 | 5240 |
| 5197 void HGraphBuilder::GenerateSetValueOf(CallRuntime* call) { | 5241 void HGraphBuilder::GenerateSetValueOf(CallRuntime* call) { |
| 5198 BAILOUT("inlined runtime function: SetValueOf"); | 5242 BAILOUT("inlined runtime function: SetValueOf"); |
| 5199 } | 5243 } |
| 5200 | 5244 |
| 5201 | 5245 |
| 5202 // Fast support for charCodeAt(n). | 5246 // Fast support for charCodeAt(n). |
| 5203 void HGraphBuilder::GenerateStringCharCodeAt(CallRuntime* call) { | 5247 void HGraphBuilder::GenerateStringCharCodeAt(CallRuntime* call) { |
| 5204 ASSERT(call->arguments()->length() == 2); | 5248 ASSERT(call->arguments()->length() == 2); |
| 5205 VISIT_FOR_VALUE(call->arguments()->at(0)); | 5249 VISIT_FOR_VALUE(call->arguments()->at(0)); |
| 5206 VISIT_FOR_VALUE(call->arguments()->at(1)); | 5250 VISIT_FOR_VALUE(call->arguments()->at(1)); |
| 5207 HValue* index = Pop(); | 5251 HValue* index = Pop(); |
| 5208 HValue* string = Pop(); | 5252 HValue* string = Pop(); |
| 5209 HStringCharCodeAt* result = BuildStringCharCodeAt(string, index); | 5253 HStringCharCodeAt* result = BuildStringCharCodeAt(string, index); |
| 5210 ast_context()->ReturnInstruction(result, call->id()); | 5254 ast_context()->ReturnInstruction(result, call->id()); |
| 5211 } | 5255 } |
| 5212 | 5256 |
| 5213 | 5257 |
| 5214 // Fast support for string.charAt(n) and string[n]. | 5258 // Fast support for string.charAt(n) and string[n]. |
| 5215 void HGraphBuilder::GenerateStringCharFromCode(CallRuntime* call) { | 5259 void HGraphBuilder::GenerateStringCharFromCode(CallRuntime* call) { |
| 5216 ASSERT(call->arguments()->length() == 1); | 5260 ASSERT(call->arguments()->length() == 1); |
| 5217 VISIT_FOR_VALUE(call->arguments()->at(0)); | 5261 VISIT_FOR_VALUE(call->arguments()->at(0)); |
| 5218 HValue* char_code = Pop(); | 5262 HValue* char_code = Pop(); |
| 5219 HStringCharFromCode* result = new HStringCharFromCode(char_code); | 5263 HStringCharFromCode* result = new(zone()) HStringCharFromCode(char_code); |
| 5220 ast_context()->ReturnInstruction(result, call->id()); | 5264 ast_context()->ReturnInstruction(result, call->id()); |
| 5221 } | 5265 } |
| 5222 | 5266 |
| 5223 | 5267 |
| 5224 // Fast support for string.charAt(n) and string[n]. | 5268 // Fast support for string.charAt(n) and string[n]. |
| 5225 void HGraphBuilder::GenerateStringCharAt(CallRuntime* call) { | 5269 void HGraphBuilder::GenerateStringCharAt(CallRuntime* call) { |
| 5226 ASSERT(call->arguments()->length() == 2); | 5270 ASSERT(call->arguments()->length() == 2); |
| 5227 VISIT_FOR_VALUE(call->arguments()->at(0)); | 5271 VISIT_FOR_VALUE(call->arguments()->at(0)); |
| 5228 VISIT_FOR_VALUE(call->arguments()->at(1)); | 5272 VISIT_FOR_VALUE(call->arguments()->at(1)); |
| 5229 HValue* index = Pop(); | 5273 HValue* index = Pop(); |
| 5230 HValue* string = Pop(); | 5274 HValue* string = Pop(); |
| 5231 HStringCharCodeAt* char_code = BuildStringCharCodeAt(string, index); | 5275 HStringCharCodeAt* char_code = BuildStringCharCodeAt(string, index); |
| 5232 AddInstruction(char_code); | 5276 AddInstruction(char_code); |
| 5233 HStringCharFromCode* result = new HStringCharFromCode(char_code); | 5277 HStringCharFromCode* result = new(zone()) HStringCharFromCode(char_code); |
| 5234 ast_context()->ReturnInstruction(result, call->id()); | 5278 ast_context()->ReturnInstruction(result, call->id()); |
| 5235 } | 5279 } |
| 5236 | 5280 |
| 5237 | 5281 |
| 5238 // Fast support for object equality testing. | 5282 // Fast support for object equality testing. |
| 5239 void HGraphBuilder::GenerateObjectEquals(CallRuntime* call) { | 5283 void HGraphBuilder::GenerateObjectEquals(CallRuntime* call) { |
| 5240 ASSERT(call->arguments()->length() == 2); | 5284 ASSERT(call->arguments()->length() == 2); |
| 5241 VISIT_FOR_VALUE(call->arguments()->at(0)); | 5285 VISIT_FOR_VALUE(call->arguments()->at(0)); |
| 5242 VISIT_FOR_VALUE(call->arguments()->at(1)); | 5286 VISIT_FOR_VALUE(call->arguments()->at(1)); |
| 5243 HValue* right = Pop(); | 5287 HValue* right = Pop(); |
| 5244 HValue* left = Pop(); | 5288 HValue* left = Pop(); |
| 5245 HCompareJSObjectEq* result = new HCompareJSObjectEq(left, right); | 5289 HCompareJSObjectEq* result = new(zone()) HCompareJSObjectEq(left, right); |
| 5246 ast_context()->ReturnInstruction(result, call->id()); | 5290 ast_context()->ReturnInstruction(result, call->id()); |
| 5247 } | 5291 } |
| 5248 | 5292 |
| 5249 | 5293 |
| 5250 void HGraphBuilder::GenerateLog(CallRuntime* call) { | 5294 void HGraphBuilder::GenerateLog(CallRuntime* call) { |
| 5251 // %_Log is ignored in optimized code. | 5295 // %_Log is ignored in optimized code. |
| 5252 ast_context()->ReturnValue(graph()->GetConstantUndefined()); | 5296 ast_context()->ReturnValue(graph()->GetConstantUndefined()); |
| 5253 } | 5297 } |
| 5254 | 5298 |
| 5255 | 5299 |
| 5256 // Fast support for Math.random(). | 5300 // Fast support for Math.random(). |
| 5257 void HGraphBuilder::GenerateRandomHeapNumber(CallRuntime* call) { | 5301 void HGraphBuilder::GenerateRandomHeapNumber(CallRuntime* call) { |
| 5258 BAILOUT("inlined runtime function: RandomHeapNumber"); | 5302 BAILOUT("inlined runtime function: RandomHeapNumber"); |
| 5259 } | 5303 } |
| 5260 | 5304 |
| 5261 | 5305 |
| 5262 // Fast support for StringAdd. | 5306 // Fast support for StringAdd. |
| 5263 void HGraphBuilder::GenerateStringAdd(CallRuntime* call) { | 5307 void HGraphBuilder::GenerateStringAdd(CallRuntime* call) { |
| 5264 ASSERT_EQ(2, call->arguments()->length()); | 5308 ASSERT_EQ(2, call->arguments()->length()); |
| 5265 VisitArgumentList(call->arguments()); | 5309 VisitArgumentList(call->arguments()); |
| 5266 CHECK_BAILOUT; | 5310 CHECK_BAILOUT; |
| 5267 HContext* context = new HContext; | 5311 HContext* context = new(zone()) HContext; |
| 5268 AddInstruction(context); | 5312 AddInstruction(context); |
| 5269 HCallStub* result = new HCallStub(context, CodeStub::StringAdd, 2); | 5313 HCallStub* result = new(zone()) HCallStub(context, CodeStub::StringAdd, 2); |
| 5270 Drop(2); | 5314 Drop(2); |
| 5271 ast_context()->ReturnInstruction(result, call->id()); | 5315 ast_context()->ReturnInstruction(result, call->id()); |
| 5272 } | 5316 } |
| 5273 | 5317 |
| 5274 | 5318 |
| 5275 // Fast support for SubString. | 5319 // Fast support for SubString. |
| 5276 void HGraphBuilder::GenerateSubString(CallRuntime* call) { | 5320 void HGraphBuilder::GenerateSubString(CallRuntime* call) { |
| 5277 ASSERT_EQ(3, call->arguments()->length()); | 5321 ASSERT_EQ(3, call->arguments()->length()); |
| 5278 VisitArgumentList(call->arguments()); | 5322 VisitArgumentList(call->arguments()); |
| 5279 CHECK_BAILOUT; | 5323 CHECK_BAILOUT; |
| 5280 HContext* context = new HContext; | 5324 HContext* context = new(zone()) HContext; |
| 5281 AddInstruction(context); | 5325 AddInstruction(context); |
| 5282 HCallStub* result = new HCallStub(context, CodeStub::SubString, 3); | 5326 HCallStub* result = new(zone()) HCallStub(context, CodeStub::SubString, 3); |
| 5283 Drop(3); | 5327 Drop(3); |
| 5284 ast_context()->ReturnInstruction(result, call->id()); | 5328 ast_context()->ReturnInstruction(result, call->id()); |
| 5285 } | 5329 } |
| 5286 | 5330 |
| 5287 | 5331 |
| 5288 // Fast support for StringCompare. | 5332 // Fast support for StringCompare. |
| 5289 void HGraphBuilder::GenerateStringCompare(CallRuntime* call) { | 5333 void HGraphBuilder::GenerateStringCompare(CallRuntime* call) { |
| 5290 ASSERT_EQ(2, call->arguments()->length()); | 5334 ASSERT_EQ(2, call->arguments()->length()); |
| 5291 VisitArgumentList(call->arguments()); | 5335 VisitArgumentList(call->arguments()); |
| 5292 CHECK_BAILOUT; | 5336 CHECK_BAILOUT; |
| 5293 HContext* context = new HContext; | 5337 HContext* context = new(zone()) HContext; |
| 5294 AddInstruction(context); | 5338 AddInstruction(context); |
| 5295 HCallStub* result = new HCallStub(context, CodeStub::StringCompare, 2); | 5339 HCallStub* result = |
| 5340 new(zone()) HCallStub(context, CodeStub::StringCompare, 2); |
| 5296 Drop(2); | 5341 Drop(2); |
| 5297 ast_context()->ReturnInstruction(result, call->id()); | 5342 ast_context()->ReturnInstruction(result, call->id()); |
| 5298 } | 5343 } |
| 5299 | 5344 |
| 5300 | 5345 |
| 5301 // Support for direct calls from JavaScript to native RegExp code. | 5346 // Support for direct calls from JavaScript to native RegExp code. |
| 5302 void HGraphBuilder::GenerateRegExpExec(CallRuntime* call) { | 5347 void HGraphBuilder::GenerateRegExpExec(CallRuntime* call) { |
| 5303 ASSERT_EQ(4, call->arguments()->length()); | 5348 ASSERT_EQ(4, call->arguments()->length()); |
| 5304 VisitArgumentList(call->arguments()); | 5349 VisitArgumentList(call->arguments()); |
| 5305 CHECK_BAILOUT; | 5350 CHECK_BAILOUT; |
| 5306 HContext* context = new HContext; | 5351 HContext* context = new(zone()) HContext; |
| 5307 AddInstruction(context); | 5352 AddInstruction(context); |
| 5308 HCallStub* result = new HCallStub(context, CodeStub::RegExpExec, 4); | 5353 HCallStub* result = new(zone()) HCallStub(context, CodeStub::RegExpExec, 4); |
| 5309 Drop(4); | 5354 Drop(4); |
| 5310 ast_context()->ReturnInstruction(result, call->id()); | 5355 ast_context()->ReturnInstruction(result, call->id()); |
| 5311 } | 5356 } |
| 5312 | 5357 |
| 5313 | 5358 |
| 5314 // Construct a RegExp exec result with two in-object properties. | 5359 // Construct a RegExp exec result with two in-object properties. |
| 5315 void HGraphBuilder::GenerateRegExpConstructResult(CallRuntime* call) { | 5360 void HGraphBuilder::GenerateRegExpConstructResult(CallRuntime* call) { |
| 5316 ASSERT_EQ(3, call->arguments()->length()); | 5361 ASSERT_EQ(3, call->arguments()->length()); |
| 5317 VisitArgumentList(call->arguments()); | 5362 VisitArgumentList(call->arguments()); |
| 5318 CHECK_BAILOUT; | 5363 CHECK_BAILOUT; |
| 5319 HContext* context = new HContext; | 5364 HContext* context = new(zone()) HContext; |
| 5320 AddInstruction(context); | 5365 AddInstruction(context); |
| 5321 HCallStub* result = | 5366 HCallStub* result = |
| 5322 new HCallStub(context, CodeStub::RegExpConstructResult, 3); | 5367 new(zone()) HCallStub(context, CodeStub::RegExpConstructResult, 3); |
| 5323 Drop(3); | 5368 Drop(3); |
| 5324 ast_context()->ReturnInstruction(result, call->id()); | 5369 ast_context()->ReturnInstruction(result, call->id()); |
| 5325 } | 5370 } |
| 5326 | 5371 |
| 5327 | 5372 |
| 5328 // Support for fast native caches. | 5373 // Support for fast native caches. |
| 5329 void HGraphBuilder::GenerateGetFromCache(CallRuntime* call) { | 5374 void HGraphBuilder::GenerateGetFromCache(CallRuntime* call) { |
| 5330 BAILOUT("inlined runtime function: GetFromCache"); | 5375 BAILOUT("inlined runtime function: GetFromCache"); |
| 5331 } | 5376 } |
| 5332 | 5377 |
| 5333 | 5378 |
| 5334 // Fast support for number to string. | 5379 // Fast support for number to string. |
| 5335 void HGraphBuilder::GenerateNumberToString(CallRuntime* call) { | 5380 void HGraphBuilder::GenerateNumberToString(CallRuntime* call) { |
| 5336 ASSERT_EQ(1, call->arguments()->length()); | 5381 ASSERT_EQ(1, call->arguments()->length()); |
| 5337 VisitArgumentList(call->arguments()); | 5382 VisitArgumentList(call->arguments()); |
| 5338 CHECK_BAILOUT; | 5383 CHECK_BAILOUT; |
| 5339 HContext* context = new HContext; | 5384 HContext* context = new(zone()) HContext; |
| 5340 AddInstruction(context); | 5385 AddInstruction(context); |
| 5341 HCallStub* result = new HCallStub(context, CodeStub::NumberToString, 1); | 5386 HCallStub* result = |
| 5387 new(zone()) HCallStub(context, CodeStub::NumberToString, 1); |
| 5342 Drop(1); | 5388 Drop(1); |
| 5343 ast_context()->ReturnInstruction(result, call->id()); | 5389 ast_context()->ReturnInstruction(result, call->id()); |
| 5344 } | 5390 } |
| 5345 | 5391 |
| 5346 | 5392 |
| 5347 // Fast swapping of elements. Takes three expressions, the object and two | 5393 // Fast swapping of elements. Takes three expressions, the object and two |
| 5348 // indices. This should only be used if the indices are known to be | 5394 // indices. This should only be used if the indices are known to be |
| 5349 // non-negative and within bounds of the elements array at the call site. | 5395 // non-negative and within bounds of the elements array at the call site. |
| 5350 void HGraphBuilder::GenerateSwapElements(CallRuntime* call) { | 5396 void HGraphBuilder::GenerateSwapElements(CallRuntime* call) { |
| 5351 BAILOUT("inlined runtime function: SwapElements"); | 5397 BAILOUT("inlined runtime function: SwapElements"); |
| 5352 } | 5398 } |
| 5353 | 5399 |
| 5354 | 5400 |
| 5355 // Fast call for custom callbacks. | 5401 // Fast call for custom callbacks. |
| 5356 void HGraphBuilder::GenerateCallFunction(CallRuntime* call) { | 5402 void HGraphBuilder::GenerateCallFunction(CallRuntime* call) { |
| 5357 BAILOUT("inlined runtime function: CallFunction"); | 5403 BAILOUT("inlined runtime function: CallFunction"); |
| 5358 } | 5404 } |
| 5359 | 5405 |
| 5360 | 5406 |
| 5361 // Fast call to math functions. | 5407 // Fast call to math functions. |
| 5362 void HGraphBuilder::GenerateMathPow(CallRuntime* call) { | 5408 void HGraphBuilder::GenerateMathPow(CallRuntime* call) { |
| 5363 ASSERT_EQ(2, call->arguments()->length()); | 5409 ASSERT_EQ(2, call->arguments()->length()); |
| 5364 VISIT_FOR_VALUE(call->arguments()->at(0)); | 5410 VISIT_FOR_VALUE(call->arguments()->at(0)); |
| 5365 VISIT_FOR_VALUE(call->arguments()->at(1)); | 5411 VISIT_FOR_VALUE(call->arguments()->at(1)); |
| 5366 HValue* right = Pop(); | 5412 HValue* right = Pop(); |
| 5367 HValue* left = Pop(); | 5413 HValue* left = Pop(); |
| 5368 HPower* result = new HPower(left, right); | 5414 HPower* result = new(zone()) HPower(left, right); |
| 5369 ast_context()->ReturnInstruction(result, call->id()); | 5415 ast_context()->ReturnInstruction(result, call->id()); |
| 5370 } | 5416 } |
| 5371 | 5417 |
| 5372 | 5418 |
| 5373 void HGraphBuilder::GenerateMathSin(CallRuntime* call) { | 5419 void HGraphBuilder::GenerateMathSin(CallRuntime* call) { |
| 5374 ASSERT_EQ(1, call->arguments()->length()); | 5420 ASSERT_EQ(1, call->arguments()->length()); |
| 5375 VisitArgumentList(call->arguments()); | 5421 VisitArgumentList(call->arguments()); |
| 5376 CHECK_BAILOUT; | 5422 CHECK_BAILOUT; |
| 5377 HContext* context = new HContext; | 5423 HContext* context = new(zone()) HContext; |
| 5378 AddInstruction(context); | 5424 AddInstruction(context); |
| 5379 HCallStub* result = new HCallStub(context, CodeStub::TranscendentalCache, 1); | 5425 HCallStub* result = |
| 5426 new(zone()) HCallStub(context, CodeStub::TranscendentalCache, 1); |
| 5380 result->set_transcendental_type(TranscendentalCache::SIN); | 5427 result->set_transcendental_type(TranscendentalCache::SIN); |
| 5381 Drop(1); | 5428 Drop(1); |
| 5382 ast_context()->ReturnInstruction(result, call->id()); | 5429 ast_context()->ReturnInstruction(result, call->id()); |
| 5383 } | 5430 } |
| 5384 | 5431 |
| 5385 | 5432 |
| 5386 void HGraphBuilder::GenerateMathCos(CallRuntime* call) { | 5433 void HGraphBuilder::GenerateMathCos(CallRuntime* call) { |
| 5387 ASSERT_EQ(1, call->arguments()->length()); | 5434 ASSERT_EQ(1, call->arguments()->length()); |
| 5388 VisitArgumentList(call->arguments()); | 5435 VisitArgumentList(call->arguments()); |
| 5389 CHECK_BAILOUT; | 5436 CHECK_BAILOUT; |
| 5390 HContext* context = new HContext; | 5437 HContext* context = new(zone()) HContext; |
| 5391 AddInstruction(context); | 5438 AddInstruction(context); |
| 5392 HCallStub* result = new HCallStub(context, CodeStub::TranscendentalCache, 1); | 5439 HCallStub* result = |
| 5440 new(zone()) HCallStub(context, CodeStub::TranscendentalCache, 1); |
| 5393 result->set_transcendental_type(TranscendentalCache::COS); | 5441 result->set_transcendental_type(TranscendentalCache::COS); |
| 5394 Drop(1); | 5442 Drop(1); |
| 5395 ast_context()->ReturnInstruction(result, call->id()); | 5443 ast_context()->ReturnInstruction(result, call->id()); |
| 5396 } | 5444 } |
| 5397 | 5445 |
| 5398 | 5446 |
| 5399 void HGraphBuilder::GenerateMathLog(CallRuntime* call) { | 5447 void HGraphBuilder::GenerateMathLog(CallRuntime* call) { |
| 5400 ASSERT_EQ(1, call->arguments()->length()); | 5448 ASSERT_EQ(1, call->arguments()->length()); |
| 5401 VisitArgumentList(call->arguments()); | 5449 VisitArgumentList(call->arguments()); |
| 5402 CHECK_BAILOUT; | 5450 CHECK_BAILOUT; |
| 5403 HContext* context = new HContext; | 5451 HContext* context = new(zone()) HContext; |
| 5404 AddInstruction(context); | 5452 AddInstruction(context); |
| 5405 HCallStub* result = new HCallStub(context, CodeStub::TranscendentalCache, 1); | 5453 HCallStub* result = |
| 5454 new(zone()) HCallStub(context, CodeStub::TranscendentalCache, 1); |
| 5406 result->set_transcendental_type(TranscendentalCache::LOG); | 5455 result->set_transcendental_type(TranscendentalCache::LOG); |
| 5407 Drop(1); | 5456 Drop(1); |
| 5408 ast_context()->ReturnInstruction(result, call->id()); | 5457 ast_context()->ReturnInstruction(result, call->id()); |
| 5409 } | 5458 } |
| 5410 | 5459 |
| 5411 | 5460 |
| 5412 void HGraphBuilder::GenerateMathSqrt(CallRuntime* call) { | 5461 void HGraphBuilder::GenerateMathSqrt(CallRuntime* call) { |
| 5413 BAILOUT("inlined runtime function: MathSqrt"); | 5462 BAILOUT("inlined runtime function: MathSqrt"); |
| 5414 } | 5463 } |
| 5415 | 5464 |
| 5416 | 5465 |
| 5417 // Check whether two RegExps are equivalent | 5466 // Check whether two RegExps are equivalent |
| 5418 void HGraphBuilder::GenerateIsRegExpEquivalent(CallRuntime* call) { | 5467 void HGraphBuilder::GenerateIsRegExpEquivalent(CallRuntime* call) { |
| 5419 BAILOUT("inlined runtime function: IsRegExpEquivalent"); | 5468 BAILOUT("inlined runtime function: IsRegExpEquivalent"); |
| 5420 } | 5469 } |
| 5421 | 5470 |
| 5422 | 5471 |
| 5423 void HGraphBuilder::GenerateGetCachedArrayIndex(CallRuntime* call) { | 5472 void HGraphBuilder::GenerateGetCachedArrayIndex(CallRuntime* call) { |
| 5424 ASSERT(call->arguments()->length() == 1); | 5473 ASSERT(call->arguments()->length() == 1); |
| 5425 VISIT_FOR_VALUE(call->arguments()->at(0)); | 5474 VISIT_FOR_VALUE(call->arguments()->at(0)); |
| 5426 HValue* value = Pop(); | 5475 HValue* value = Pop(); |
| 5427 HGetCachedArrayIndex* result = new HGetCachedArrayIndex(value); | 5476 HGetCachedArrayIndex* result = new(zone()) HGetCachedArrayIndex(value); |
| 5428 ast_context()->ReturnInstruction(result, call->id()); | 5477 ast_context()->ReturnInstruction(result, call->id()); |
| 5429 } | 5478 } |
| 5430 | 5479 |
| 5431 | 5480 |
| 5432 void HGraphBuilder::GenerateFastAsciiArrayJoin(CallRuntime* call) { | 5481 void HGraphBuilder::GenerateFastAsciiArrayJoin(CallRuntime* call) { |
| 5433 BAILOUT("inlined runtime function: FastAsciiArrayJoin"); | 5482 BAILOUT("inlined runtime function: FastAsciiArrayJoin"); |
| 5434 } | 5483 } |
| 5435 | 5484 |
| 5436 | 5485 |
| 5437 #undef BAILOUT | 5486 #undef BAILOUT |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5506 if (value != NULL && value->IsPhi() && value->block() == block) { | 5555 if (value != NULL && value->IsPhi() && value->block() == block) { |
| 5507 // There is already a phi for the i'th value. | 5556 // There is already a phi for the i'th value. |
| 5508 HPhi* phi = HPhi::cast(value); | 5557 HPhi* phi = HPhi::cast(value); |
| 5509 // Assert index is correct and that we haven't missed an incoming edge. | 5558 // Assert index is correct and that we haven't missed an incoming edge. |
| 5510 ASSERT(phi->merged_index() == i); | 5559 ASSERT(phi->merged_index() == i); |
| 5511 ASSERT(phi->OperandCount() == block->predecessors()->length()); | 5560 ASSERT(phi->OperandCount() == block->predecessors()->length()); |
| 5512 phi->AddInput(other->values_[i]); | 5561 phi->AddInput(other->values_[i]); |
| 5513 } else if (values_[i] != other->values_[i]) { | 5562 } else if (values_[i] != other->values_[i]) { |
| 5514 // There is a fresh value on the incoming edge, a phi is needed. | 5563 // There is a fresh value on the incoming edge, a phi is needed. |
| 5515 ASSERT(values_[i] != NULL && other->values_[i] != NULL); | 5564 ASSERT(values_[i] != NULL && other->values_[i] != NULL); |
| 5516 HPhi* phi = new HPhi(i); | 5565 HPhi* phi = new(block->zone()) HPhi(i); |
| 5517 HValue* old_value = values_[i]; | 5566 HValue* old_value = values_[i]; |
| 5518 for (int j = 0; j < block->predecessors()->length(); j++) { | 5567 for (int j = 0; j < block->predecessors()->length(); j++) { |
| 5519 phi->AddInput(old_value); | 5568 phi->AddInput(old_value); |
| 5520 } | 5569 } |
| 5521 phi->AddInput(other->values_[i]); | 5570 phi->AddInput(other->values_[i]); |
| 5522 this->values_[i] = phi; | 5571 this->values_[i] = phi; |
| 5523 block->AddPhi(phi); | 5572 block->AddPhi(phi); |
| 5524 } | 5573 } |
| 5525 } | 5574 } |
| 5526 } | 5575 } |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5563 | 5612 |
| 5564 | 5613 |
| 5565 void HEnvironment::Drop(int count) { | 5614 void HEnvironment::Drop(int count) { |
| 5566 for (int i = 0; i < count; ++i) { | 5615 for (int i = 0; i < count; ++i) { |
| 5567 Pop(); | 5616 Pop(); |
| 5568 } | 5617 } |
| 5569 } | 5618 } |
| 5570 | 5619 |
| 5571 | 5620 |
| 5572 HEnvironment* HEnvironment::Copy() const { | 5621 HEnvironment* HEnvironment::Copy() const { |
| 5573 return new HEnvironment(this); | 5622 return new(closure()->GetIsolate()->zone()) HEnvironment(this); |
| 5574 } | 5623 } |
| 5575 | 5624 |
| 5576 | 5625 |
| 5577 HEnvironment* HEnvironment::CopyWithoutHistory() const { | 5626 HEnvironment* HEnvironment::CopyWithoutHistory() const { |
| 5578 HEnvironment* result = Copy(); | 5627 HEnvironment* result = Copy(); |
| 5579 result->ClearHistory(); | 5628 result->ClearHistory(); |
| 5580 return result; | 5629 return result; |
| 5581 } | 5630 } |
| 5582 | 5631 |
| 5583 | 5632 |
| 5584 HEnvironment* HEnvironment::CopyAsLoopHeader(HBasicBlock* loop_header) const { | 5633 HEnvironment* HEnvironment::CopyAsLoopHeader(HBasicBlock* loop_header) const { |
| 5585 HEnvironment* new_env = Copy(); | 5634 HEnvironment* new_env = Copy(); |
| 5586 for (int i = 0; i < values_.length(); ++i) { | 5635 for (int i = 0; i < values_.length(); ++i) { |
| 5587 HPhi* phi = new HPhi(i); | 5636 HPhi* phi = new(loop_header->zone()) HPhi(i); |
| 5588 phi->AddInput(values_[i]); | 5637 phi->AddInput(values_[i]); |
| 5589 new_env->values_[i] = phi; | 5638 new_env->values_[i] = phi; |
| 5590 loop_header->AddPhi(phi); | 5639 loop_header->AddPhi(phi); |
| 5591 } | 5640 } |
| 5592 new_env->ClearHistory(); | 5641 new_env->ClearHistory(); |
| 5593 return new_env; | 5642 return new_env; |
| 5594 } | 5643 } |
| 5595 | 5644 |
| 5596 | 5645 |
| 5597 HEnvironment* HEnvironment::CopyForInlining(Handle<JSFunction> target, | 5646 HEnvironment* HEnvironment::CopyForInlining(Handle<JSFunction> target, |
| 5598 FunctionLiteral* function, | 5647 FunctionLiteral* function, |
| 5599 bool is_speculative, | 5648 bool is_speculative, |
| 5600 HConstant* undefined) const { | 5649 HConstant* undefined) const { |
| 5601 // Outer environment is a copy of this one without the arguments. | 5650 // Outer environment is a copy of this one without the arguments. |
| 5602 int arity = function->scope()->num_parameters(); | 5651 int arity = function->scope()->num_parameters(); |
| 5603 HEnvironment* outer = Copy(); | 5652 HEnvironment* outer = Copy(); |
| 5604 outer->Drop(arity + 1); // Including receiver. | 5653 outer->Drop(arity + 1); // Including receiver. |
| 5605 outer->ClearHistory(); | 5654 outer->ClearHistory(); |
| 5606 HEnvironment* inner = new HEnvironment(outer, function->scope(), target); | 5655 Zone* zone = closure()->GetIsolate()->zone(); |
| 5656 HEnvironment* inner = |
| 5657 new(zone) HEnvironment(outer, function->scope(), target); |
| 5607 // Get the argument values from the original environment. | 5658 // Get the argument values from the original environment. |
| 5608 if (is_speculative) { | 5659 if (is_speculative) { |
| 5609 for (int i = 0; i <= arity; ++i) { // Include receiver. | 5660 for (int i = 0; i <= arity; ++i) { // Include receiver. |
| 5610 HValue* push = ExpressionStackAt(arity - i); | 5661 HValue* push = ExpressionStackAt(arity - i); |
| 5611 inner->SetValueAt(i, push); | 5662 inner->SetValueAt(i, push); |
| 5612 } | 5663 } |
| 5613 } else { | 5664 } else { |
| 5614 for (int i = 0; i <= arity; ++i) { // Include receiver. | 5665 for (int i = 0; i <= arity; ++i) { // Include receiver. |
| 5615 inner->SetValueAt(i, ExpressionStackAt(arity - i)); | 5666 inner->SetValueAt(i, ExpressionStackAt(arity - i)); |
| 5616 } | 5667 } |
| (...skipping 334 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5951 } | 6002 } |
| 5952 } | 6003 } |
| 5953 | 6004 |
| 5954 #ifdef DEBUG | 6005 #ifdef DEBUG |
| 5955 if (graph_ != NULL) graph_->Verify(); | 6006 if (graph_ != NULL) graph_->Verify(); |
| 5956 if (allocator_ != NULL) allocator_->Verify(); | 6007 if (allocator_ != NULL) allocator_->Verify(); |
| 5957 #endif | 6008 #endif |
| 5958 } | 6009 } |
| 5959 | 6010 |
| 5960 } } // namespace v8::internal | 6011 } } // namespace v8::internal |
| OLD | NEW |