| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 787 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 798 void HGraphBuilder::IfBuilder::Then() { | 798 void HGraphBuilder::IfBuilder::Then() { |
| 799 ASSERT(!captured_); | 799 ASSERT(!captured_); |
| 800 ASSERT(!finished_); | 800 ASSERT(!finished_); |
| 801 did_then_ = true; | 801 did_then_ = true; |
| 802 if (needs_compare_) { | 802 if (needs_compare_) { |
| 803 // Handle if's without any expressions, they jump directly to the "else" | 803 // Handle if's without any expressions, they jump directly to the "else" |
| 804 // branch. However, we must pretend that the "then" branch is reachable, | 804 // branch. However, we must pretend that the "then" branch is reachable, |
| 805 // so that the graph builder visits it and sees any live range extending | 805 // so that the graph builder visits it and sees any live range extending |
| 806 // constructs within it. | 806 // constructs within it. |
| 807 HConstant* constant_false = builder_->graph()->GetConstantFalse(); | 807 HConstant* constant_false = builder_->graph()->GetConstantFalse(); |
| 808 ToBooleanStub::Types boolean_type = ToBooleanStub::no_types(); | 808 ToBooleanStub::Types boolean_type = ToBooleanStub::Types(); |
| 809 boolean_type.Add(ToBooleanStub::BOOLEAN); | 809 boolean_type.Add(ToBooleanStub::BOOLEAN); |
| 810 HBranch* branch = | 810 HBranch* branch = |
| 811 new(zone()) HBranch(constant_false, first_true_block_, | 811 new(zone()) HBranch(constant_false, first_true_block_, |
| 812 first_false_block_, boolean_type); | 812 first_false_block_, boolean_type); |
| 813 builder_->current_block()->Finish(branch); | 813 builder_->current_block()->Finish(branch); |
| 814 } | 814 } |
| 815 builder_->set_current_block(first_true_block_); | 815 builder_->set_current_block(first_true_block_); |
| 816 } | 816 } |
| 817 | 817 |
| 818 | 818 |
| (...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 958 builder_->set_current_block(exit_block_); | 958 builder_->set_current_block(exit_block_); |
| 959 // Pop the phi from the expression stack | 959 // Pop the phi from the expression stack |
| 960 builder_->environment()->Pop(); | 960 builder_->environment()->Pop(); |
| 961 finished_ = true; | 961 finished_ = true; |
| 962 } | 962 } |
| 963 | 963 |
| 964 | 964 |
| 965 HGraph* HGraphBuilder::CreateGraph() { | 965 HGraph* HGraphBuilder::CreateGraph() { |
| 966 graph_ = new(zone()) HGraph(info_); | 966 graph_ = new(zone()) HGraph(info_); |
| 967 if (FLAG_hydrogen_stats) isolate()->GetHStatistics()->Initialize(info_); | 967 if (FLAG_hydrogen_stats) isolate()->GetHStatistics()->Initialize(info_); |
| 968 HPhase phase("H_Block building", isolate(), zone()); | 968 CompilationPhase phase("H_Block building", info_); |
| 969 set_current_block(graph()->entry_block()); | 969 set_current_block(graph()->entry_block()); |
| 970 if (!BuildGraph()) return NULL; | 970 if (!BuildGraph()) return NULL; |
| 971 graph()->FinalizeUniqueValueIds(); | 971 graph()->FinalizeUniqueValueIds(); |
| 972 return graph_; | 972 return graph_; |
| 973 } | 973 } |
| 974 | 974 |
| 975 | 975 |
| 976 HInstruction* HGraphBuilder::AddInstruction(HInstruction* instr) { | 976 HInstruction* HGraphBuilder::AddInstruction(HInstruction* instr) { |
| 977 ASSERT(current_block() != NULL); | 977 ASSERT(current_block() != NULL); |
| 978 current_block()->AddInstruction(instr); | 978 current_block()->AddInstruction(instr); |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1019 | 1019 |
| 1020 HBasicBlock* HGraphBuilder::CreateLoopHeaderBlock() { | 1020 HBasicBlock* HGraphBuilder::CreateLoopHeaderBlock() { |
| 1021 HBasicBlock* header = graph()->CreateBasicBlock(); | 1021 HBasicBlock* header = graph()->CreateBasicBlock(); |
| 1022 HEnvironment* entry_env = environment()->CopyAsLoopHeader(header); | 1022 HEnvironment* entry_env = environment()->CopyAsLoopHeader(header); |
| 1023 header->SetInitialEnvironment(entry_env); | 1023 header->SetInitialEnvironment(entry_env); |
| 1024 header->AttachLoopInformation(); | 1024 header->AttachLoopInformation(); |
| 1025 return header; | 1025 return header; |
| 1026 } | 1026 } |
| 1027 | 1027 |
| 1028 | 1028 |
| 1029 HValue* HGraphBuilder::BuildCheckNonSmi(HValue* obj) { | 1029 HValue* HGraphBuilder::BuildCheckHeapObject(HValue* obj) { |
| 1030 if (obj->type().IsHeapObject()) return obj; | 1030 if (obj->type().IsHeapObject()) return obj; |
| 1031 HCheckNonSmi* check = new(zone()) HCheckNonSmi(obj); | 1031 HCheckHeapObject* check = new(zone()) HCheckHeapObject(obj); |
| 1032 AddInstruction(check); | 1032 AddInstruction(check); |
| 1033 return check; | 1033 return check; |
| 1034 } | 1034 } |
| 1035 | 1035 |
| 1036 | 1036 |
| 1037 HValue* HGraphBuilder::BuildCheckMap(HValue* obj, | 1037 HValue* HGraphBuilder::BuildCheckMap(HValue* obj, |
| 1038 Handle<Map> map) { | 1038 Handle<Map> map) { |
| 1039 HCheckMaps* check = HCheckMaps::New(obj, map, zone()); | 1039 HCheckMaps* check = HCheckMaps::New(obj, map, zone()); |
| 1040 AddInstruction(check); | 1040 AddInstruction(check); |
| 1041 return check; | 1041 return check; |
| (...skipping 656 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1698 graph()->GetConstantUndefined()); | 1698 graph()->GetConstantUndefined()); |
| 1699 needs_or = true; | 1699 needs_or = true; |
| 1700 } | 1700 } |
| 1701 if (type->Maybe(Type::Undetectable())) { | 1701 if (type->Maybe(Type::Undetectable())) { |
| 1702 if (needs_or) if_nil.Or(); | 1702 if (needs_or) if_nil.Or(); |
| 1703 if_nil.If<HIsUndetectableAndBranch>(value); | 1703 if_nil.If<HIsUndetectableAndBranch>(value); |
| 1704 } else { | 1704 } else { |
| 1705 if_nil.Then(); | 1705 if_nil.Then(); |
| 1706 if_nil.Else(); | 1706 if_nil.Else(); |
| 1707 if (type->NumClasses() == 1) { | 1707 if (type->NumClasses() == 1) { |
| 1708 BuildCheckNonSmi(value); | 1708 BuildCheckHeapObject(value); |
| 1709 // For ICs, the map checked below is a sentinel map that gets replaced by | 1709 // For ICs, the map checked below is a sentinel map that gets replaced by |
| 1710 // the monomorphic map when the code is used as a template to generate a | 1710 // the monomorphic map when the code is used as a template to generate a |
| 1711 // new IC. For optimized functions, there is no sentinel map, the map | 1711 // new IC. For optimized functions, there is no sentinel map, the map |
| 1712 // emitted below is the actual monomorphic map. | 1712 // emitted below is the actual monomorphic map. |
| 1713 BuildCheckMap(value, type->Classes().Current()); | 1713 BuildCheckMap(value, type->Classes().Current()); |
| 1714 } else { | 1714 } else { |
| 1715 if_nil.Deopt(); | 1715 if_nil.Deopt(); |
| 1716 } | 1716 } |
| 1717 } | 1717 } |
| 1718 | 1718 |
| (...skipping 660 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2379 HLoopInformation* loop_; | 2379 HLoopInformation* loop_; |
| 2380 HBasicBlock* block_; | 2380 HBasicBlock* block_; |
| 2381 HBasicBlock* loop_header_; | 2381 HBasicBlock* loop_header_; |
| 2382 int loop_index; | 2382 int loop_index; |
| 2383 int loop_length; | 2383 int loop_length; |
| 2384 HSuccessorIterator successor_iterator; | 2384 HSuccessorIterator successor_iterator; |
| 2385 }; | 2385 }; |
| 2386 | 2386 |
| 2387 | 2387 |
| 2388 void HGraph::OrderBlocks() { | 2388 void HGraph::OrderBlocks() { |
| 2389 HPhase phase("H_Block ordering", isolate(), zone()); | 2389 CompilationPhase phase("H_Block ordering", info()); |
| 2390 BitVector visited(blocks_.length(), zone()); | 2390 BitVector visited(blocks_.length(), zone()); |
| 2391 | 2391 |
| 2392 ZoneList<HBasicBlock*> reverse_result(8, zone()); | 2392 ZoneList<HBasicBlock*> reverse_result(8, zone()); |
| 2393 HBasicBlock* start = blocks_[0]; | 2393 HBasicBlock* start = blocks_[0]; |
| 2394 PostorderProcessor* postorder = | 2394 PostorderProcessor* postorder = |
| 2395 PostorderProcessor::CreateEntryProcessor(zone(), start, &visited); | 2395 PostorderProcessor::CreateEntryProcessor(zone(), start, &visited); |
| 2396 while (postorder != NULL) { | 2396 while (postorder != NULL) { |
| 2397 postorder = postorder->PerformStep(zone(), &visited, &reverse_result); | 2397 postorder = postorder->PerformStep(zone(), &visited, &reverse_result); |
| 2398 } | 2398 } |
| 2399 blocks_.Rewind(0); | 2399 blocks_.Rewind(0); |
| (...skipping 284 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2684 Analyze(block->dominated_blocks()->at(i)); | 2684 Analyze(block->dominated_blocks()->at(i)); |
| 2685 } | 2685 } |
| 2686 | 2686 |
| 2687 RollBackTo(last_changed_range); | 2687 RollBackTo(last_changed_range); |
| 2688 } | 2688 } |
| 2689 | 2689 |
| 2690 | 2690 |
| 2691 void HRangeAnalysis::InferControlFlowRange(HCompareIDAndBranch* test, | 2691 void HRangeAnalysis::InferControlFlowRange(HCompareIDAndBranch* test, |
| 2692 HBasicBlock* dest) { | 2692 HBasicBlock* dest) { |
| 2693 ASSERT((test->FirstSuccessor() == dest) == (test->SecondSuccessor() != dest)); | 2693 ASSERT((test->FirstSuccessor() == dest) == (test->SecondSuccessor() != dest)); |
| 2694 if (test->representation().IsInteger32()) { | 2694 if (test->representation().IsSmiOrInteger32()) { |
| 2695 Token::Value op = test->token(); | 2695 Token::Value op = test->token(); |
| 2696 if (test->SecondSuccessor() == dest) { | 2696 if (test->SecondSuccessor() == dest) { |
| 2697 op = Token::NegateCompareOp(op); | 2697 op = Token::NegateCompareOp(op); |
| 2698 } | 2698 } |
| 2699 Token::Value inverted_op = Token::ReverseCompareOp(op); | 2699 Token::Value inverted_op = Token::ReverseCompareOp(op); |
| 2700 UpdateControlFlowRange(op, test->left(), test->right()); | 2700 UpdateControlFlowRange(op, test->left(), test->right()); |
| 2701 UpdateControlFlowRange(inverted_op, test->right(), test->left()); | 2701 UpdateControlFlowRange(inverted_op, test->right(), test->left()); |
| 2702 } | 2702 } |
| 2703 } | 2703 } |
| 2704 | 2704 |
| (...skipping 243 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2948 for (int j = 0; j < phis->length(); ++j) { | 2948 for (int j = 0; j < phis->length(); ++j) { |
| 2949 HPhi* phi = phis->at(j); | 2949 HPhi* phi = phis->at(j); |
| 2950 if (phi->representation().IsNone()) { | 2950 if (phi->representation().IsNone()) { |
| 2951 phi->ChangeRepresentation(Representation::Tagged()); | 2951 phi->ChangeRepresentation(Representation::Tagged()); |
| 2952 } | 2952 } |
| 2953 } | 2953 } |
| 2954 for (HInstruction* current = block->first(); | 2954 for (HInstruction* current = block->first(); |
| 2955 current != NULL; current = current->next()) { | 2955 current != NULL; current = current->next()) { |
| 2956 if (current->representation().IsNone() && | 2956 if (current->representation().IsNone() && |
| 2957 current->CheckFlag(HInstruction::kFlexibleRepresentation)) { | 2957 current->CheckFlag(HInstruction::kFlexibleRepresentation)) { |
| 2958 current->ChangeRepresentation(Representation::Tagged()); | 2958 if (current->CheckFlag(HInstruction::kCannotBeTagged)) { |
| 2959 current->ChangeRepresentation(Representation::Double()); |
| 2960 } else { |
| 2961 current->ChangeRepresentation(Representation::Tagged()); |
| 2962 } |
| 2959 } | 2963 } |
| 2960 } | 2964 } |
| 2961 } | 2965 } |
| 2962 } | 2966 } |
| 2963 | 2967 |
| 2964 | 2968 |
| 2965 void HGraph::MergeRemovableSimulates() { | 2969 void HGraph::MergeRemovableSimulates() { |
| 2966 HPhase phase("H_Merge removable simulates", this); | 2970 HPhase phase("H_Merge removable simulates", this); |
| 2967 ZoneList<HSimulate*> mergelist(2, zone()); | 2971 ZoneList<HSimulate*> mergelist(2, zone()); |
| 2968 for (int i = 0; i < blocks()->length(); ++i) { | 2972 for (int i = 0; i < blocks()->length(); ++i) { |
| (...skipping 968 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3937 int checksum = type_info->own_type_change_checksum(); | 3941 int checksum = type_info->own_type_change_checksum(); |
| 3938 int composite_checksum = graph()->update_type_change_checksum(checksum); | 3942 int composite_checksum = graph()->update_type_change_checksum(checksum); |
| 3939 graph()->set_use_optimistic_licm( | 3943 graph()->set_use_optimistic_licm( |
| 3940 !type_info->matches_inlined_type_change_checksum(composite_checksum)); | 3944 !type_info->matches_inlined_type_change_checksum(composite_checksum)); |
| 3941 type_info->set_inlined_type_change_checksum(composite_checksum); | 3945 type_info->set_inlined_type_change_checksum(composite_checksum); |
| 3942 | 3946 |
| 3943 return true; | 3947 return true; |
| 3944 } | 3948 } |
| 3945 | 3949 |
| 3946 | 3950 |
| 3947 // Perform common subexpression elimination and loop-invariant code motion. | |
| 3948 void HGraph::GlobalValueNumbering() { | |
| 3949 HPhase phase("H_Global value numbering", this); | |
| 3950 HGlobalValueNumberer gvn(this, info()); | |
| 3951 bool removed_side_effects = gvn.Analyze(); | |
| 3952 // Trigger a second analysis pass to further eliminate duplicate values that | |
| 3953 // could only be discovered by removing side-effect-generating instructions | |
| 3954 // during the first pass. | |
| 3955 if (FLAG_smi_only_arrays && removed_side_effects) { | |
| 3956 removed_side_effects = gvn.Analyze(); | |
| 3957 ASSERT(!removed_side_effects); | |
| 3958 } | |
| 3959 } | |
| 3960 | |
| 3961 | |
| 3962 bool HGraph::Optimize(SmartArrayPointer<char>* bailout_reason) { | 3951 bool HGraph::Optimize(SmartArrayPointer<char>* bailout_reason) { |
| 3963 *bailout_reason = SmartArrayPointer<char>(); | 3952 *bailout_reason = SmartArrayPointer<char>(); |
| 3964 OrderBlocks(); | 3953 OrderBlocks(); |
| 3965 AssignDominators(); | 3954 AssignDominators(); |
| 3966 | 3955 |
| 3967 // We need to create a HConstant "zero" now so that GVN will fold every | 3956 // We need to create a HConstant "zero" now so that GVN will fold every |
| 3968 // zero-valued constant in the graph together. | 3957 // zero-valued constant in the graph together. |
| 3969 // The constant is needed to make idef-based bounds check work: the pass | 3958 // The constant is needed to make idef-based bounds check work: the pass |
| 3970 // evaluates relations with "zero" and that zero cannot be created after GVN. | 3959 // evaluates relations with "zero" and that zero cannot be created after GVN. |
| 3971 GetConstant0(); | 3960 GetConstant0(); |
| 3972 | 3961 |
| 3973 #ifdef DEBUG | 3962 #ifdef DEBUG |
| 3974 // Do a full verify after building the graph and computing dominators. | 3963 // Do a full verify after building the graph and computing dominators. |
| 3975 Verify(true); | 3964 Verify(true); |
| 3976 #endif | 3965 #endif |
| 3977 | 3966 |
| 3978 if (FLAG_analyze_environment_liveness) { | 3967 if (FLAG_analyze_environment_liveness && maximum_environment_size() != 0) { |
| 3979 EnvironmentSlotLivenessAnalyzer esla(this); | 3968 Run<HEnvironmentLivenessAnalysisPhase>(); |
| 3980 esla.AnalyzeAndTrim(); | |
| 3981 } | 3969 } |
| 3982 | 3970 |
| 3983 PropagateDeoptimizingMark(); | 3971 PropagateDeoptimizingMark(); |
| 3984 if (!CheckConstPhiUses()) { | 3972 if (!CheckConstPhiUses()) { |
| 3985 *bailout_reason = SmartArrayPointer<char>(StrDup( | 3973 *bailout_reason = SmartArrayPointer<char>(StrDup( |
| 3986 "Unsupported phi use of const variable")); | 3974 "Unsupported phi use of const variable")); |
| 3987 return false; | 3975 return false; |
| 3988 } | 3976 } |
| 3989 EliminateRedundantPhis(); | 3977 EliminateRedundantPhis(); |
| 3990 if (!CheckArgumentsPhiUses()) { | 3978 if (!CheckArgumentsPhiUses()) { |
| (...skipping 29 matching lines...) Expand all Loading... |
| 4020 | 4008 |
| 4021 InitializeInferredTypes(); | 4009 InitializeInferredTypes(); |
| 4022 | 4010 |
| 4023 // Must be performed before canonicalization to ensure that Canonicalize | 4011 // Must be performed before canonicalization to ensure that Canonicalize |
| 4024 // will not remove semantically meaningful ToInt32 operations e.g. BIT_OR with | 4012 // will not remove semantically meaningful ToInt32 operations e.g. BIT_OR with |
| 4025 // zero. | 4013 // zero. |
| 4026 if (FLAG_opt_safe_uint32_operations) ComputeSafeUint32Operations(); | 4014 if (FLAG_opt_safe_uint32_operations) ComputeSafeUint32Operations(); |
| 4027 | 4015 |
| 4028 if (FLAG_use_canonicalizing) Canonicalize(); | 4016 if (FLAG_use_canonicalizing) Canonicalize(); |
| 4029 | 4017 |
| 4030 if (FLAG_use_gvn) GlobalValueNumbering(); | 4018 if (FLAG_use_gvn) Run<HGlobalValueNumberingPhase>(); |
| 4031 | 4019 |
| 4032 if (FLAG_use_range) { | 4020 if (FLAG_use_range) { |
| 4033 HRangeAnalysis rangeAnalysis(this); | 4021 HRangeAnalysis rangeAnalysis(this); |
| 4034 rangeAnalysis.Analyze(); | 4022 rangeAnalysis.Analyze(); |
| 4035 } | 4023 } |
| 4036 ComputeMinusZeroChecks(); | 4024 ComputeMinusZeroChecks(); |
| 4037 | 4025 |
| 4038 // Eliminate redundant stack checks on backwards branches. | 4026 // Eliminate redundant stack checks on backwards branches. |
| 4039 HStackCheckEliminator sce(this); | 4027 HStackCheckEliminator sce(this); |
| 4040 sce.Process(); | 4028 sce.Process(); |
| (...skipping 601 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4642 instruction->DeleteAndReplaceWith(instruction->RedefinedOperand()); | 4630 instruction->DeleteAndReplaceWith(instruction->RedefinedOperand()); |
| 4643 } else { | 4631 } else { |
| 4644 instruction->ReplaceAllUsesWith(instruction->ActualValue()); | 4632 instruction->ReplaceAllUsesWith(instruction->ActualValue()); |
| 4645 } | 4633 } |
| 4646 } | 4634 } |
| 4647 } | 4635 } |
| 4648 } | 4636 } |
| 4649 } | 4637 } |
| 4650 | 4638 |
| 4651 | 4639 |
| 4652 void HOptimizedGraphBuilder::AddPhi(HPhi* instr) { | |
| 4653 ASSERT(current_block() != NULL); | |
| 4654 current_block()->AddPhi(instr); | |
| 4655 } | |
| 4656 | |
| 4657 | |
| 4658 void HOptimizedGraphBuilder::PushAndAdd(HInstruction* instr) { | 4640 void HOptimizedGraphBuilder::PushAndAdd(HInstruction* instr) { |
| 4659 Push(instr); | 4641 Push(instr); |
| 4660 AddInstruction(instr); | 4642 AddInstruction(instr); |
| 4661 } | 4643 } |
| 4662 | 4644 |
| 4663 | 4645 |
| 4664 void HOptimizedGraphBuilder::AddSoftDeoptimize() { | 4646 void HOptimizedGraphBuilder::AddSoftDeoptimize() { |
| 4647 isolate()->counters()->soft_deopts_requested()->Increment(); |
| 4665 if (FLAG_always_opt) return; | 4648 if (FLAG_always_opt) return; |
| 4666 if (current_block()->IsDeoptimizing()) return; | 4649 if (current_block()->IsDeoptimizing()) return; |
| 4667 AddInstruction(new(zone()) HSoftDeoptimize()); | 4650 AddInstruction(new(zone()) HSoftDeoptimize()); |
| 4651 isolate()->counters()->soft_deopts_inserted()->Increment(); |
| 4668 current_block()->MarkAsDeoptimizing(); | 4652 current_block()->MarkAsDeoptimizing(); |
| 4669 graph()->set_has_soft_deoptimize(true); | 4653 graph()->set_has_soft_deoptimize(true); |
| 4670 } | 4654 } |
| 4671 | 4655 |
| 4672 | 4656 |
| 4673 template <class Instruction> | 4657 template <class Instruction> |
| 4674 HInstruction* HOptimizedGraphBuilder::PreProcessCall(Instruction* call) { | 4658 HInstruction* HOptimizedGraphBuilder::PreProcessCall(Instruction* call) { |
| 4675 int count = call->argument_count(); | 4659 int count = call->argument_count(); |
| 4676 ZoneList<HValue*> arguments(count, zone()); | 4660 ZoneList<HValue*> arguments(count, zone()); |
| 4677 for (int i = 0; i < count; ++i) { | 4661 for (int i = 0; i < count; ++i) { |
| (...skipping 332 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5010 // Generate a compare and branch. | 4994 // Generate a compare and branch. |
| 5011 CHECK_ALIVE(VisitForValue(clause->label())); | 4995 CHECK_ALIVE(VisitForValue(clause->label())); |
| 5012 HValue* label_value = Pop(); | 4996 HValue* label_value = Pop(); |
| 5013 | 4997 |
| 5014 HBasicBlock* next_test_block = graph()->CreateBasicBlock(); | 4998 HBasicBlock* next_test_block = graph()->CreateBasicBlock(); |
| 5015 HBasicBlock* body_block = graph()->CreateBasicBlock(); | 4999 HBasicBlock* body_block = graph()->CreateBasicBlock(); |
| 5016 | 5000 |
| 5017 HControlInstruction* compare; | 5001 HControlInstruction* compare; |
| 5018 | 5002 |
| 5019 if (stmt->switch_type() == SwitchStatement::SMI_SWITCH) { | 5003 if (stmt->switch_type() == SwitchStatement::SMI_SWITCH) { |
| 5020 if (!clause->compare_type()->Is(Type::Integer31())) { | 5004 if (!clause->compare_type()->Is(Type::Smi())) { |
| 5021 AddSoftDeoptimize(); | 5005 AddSoftDeoptimize(); |
| 5022 } | 5006 } |
| 5023 | 5007 |
| 5024 HCompareIDAndBranch* compare_ = | 5008 HCompareIDAndBranch* compare_ = |
| 5025 new(zone()) HCompareIDAndBranch(tag_value, | 5009 new(zone()) HCompareIDAndBranch(tag_value, |
| 5026 label_value, | 5010 label_value, |
| 5027 Token::EQ_STRICT); | 5011 Token::EQ_STRICT); |
| 5028 compare_->set_observed_input_representation( | 5012 compare_->set_observed_input_representation( |
| 5029 Representation::Smi(), Representation::Smi()); | 5013 Representation::Smi(), Representation::Smi()); |
| 5030 compare = compare_; | 5014 compare = compare_; |
| (...skipping 635 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5666 case Variable::LOOKUP: | 5650 case Variable::LOOKUP: |
| 5667 return Bailout("reference to a variable which requires dynamic lookup"); | 5651 return Bailout("reference to a variable which requires dynamic lookup"); |
| 5668 } | 5652 } |
| 5669 } | 5653 } |
| 5670 | 5654 |
| 5671 | 5655 |
| 5672 void HOptimizedGraphBuilder::VisitLiteral(Literal* expr) { | 5656 void HOptimizedGraphBuilder::VisitLiteral(Literal* expr) { |
| 5673 ASSERT(!HasStackOverflow()); | 5657 ASSERT(!HasStackOverflow()); |
| 5674 ASSERT(current_block() != NULL); | 5658 ASSERT(current_block() != NULL); |
| 5675 ASSERT(current_block()->HasPredecessor()); | 5659 ASSERT(current_block()->HasPredecessor()); |
| 5676 HConstant* instr = new(zone()) HConstant(expr->handle()); | 5660 HConstant* instr = new(zone()) HConstant(expr->value()); |
| 5677 return ast_context()->ReturnInstruction(instr, expr->id()); | 5661 return ast_context()->ReturnInstruction(instr, expr->id()); |
| 5678 } | 5662 } |
| 5679 | 5663 |
| 5680 | 5664 |
| 5681 void HOptimizedGraphBuilder::VisitRegExpLiteral(RegExpLiteral* expr) { | 5665 void HOptimizedGraphBuilder::VisitRegExpLiteral(RegExpLiteral* expr) { |
| 5682 ASSERT(!HasStackOverflow()); | 5666 ASSERT(!HasStackOverflow()); |
| 5683 ASSERT(current_block() != NULL); | 5667 ASSERT(current_block() != NULL); |
| 5684 ASSERT(current_block()->HasPredecessor()); | 5668 ASSERT(current_block()->HasPredecessor()); |
| 5685 Handle<JSFunction> closure = function_state()->compilation_info()->closure(); | 5669 Handle<JSFunction> closure = function_state()->compilation_info()->closure(); |
| 5686 Handle<FixedArray> literals(closure->literals()); | 5670 Handle<FixedArray> literals(closure->literals()); |
| (...skipping 240 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5927 if (property->IsCompileTimeValue()) continue; | 5911 if (property->IsCompileTimeValue()) continue; |
| 5928 | 5912 |
| 5929 Literal* key = property->key(); | 5913 Literal* key = property->key(); |
| 5930 Expression* value = property->value(); | 5914 Expression* value = property->value(); |
| 5931 | 5915 |
| 5932 switch (property->kind()) { | 5916 switch (property->kind()) { |
| 5933 case ObjectLiteral::Property::MATERIALIZED_LITERAL: | 5917 case ObjectLiteral::Property::MATERIALIZED_LITERAL: |
| 5934 ASSERT(!CompileTimeValue::IsCompileTimeValue(value)); | 5918 ASSERT(!CompileTimeValue::IsCompileTimeValue(value)); |
| 5935 // Fall through. | 5919 // Fall through. |
| 5936 case ObjectLiteral::Property::COMPUTED: | 5920 case ObjectLiteral::Property::COMPUTED: |
| 5937 if (key->handle()->IsInternalizedString()) { | 5921 if (key->value()->IsInternalizedString()) { |
| 5938 if (property->emit_store()) { | 5922 if (property->emit_store()) { |
| 5939 CHECK_ALIVE(VisitForValue(value)); | 5923 CHECK_ALIVE(VisitForValue(value)); |
| 5940 HValue* value = Pop(); | 5924 HValue* value = Pop(); |
| 5941 Handle<Map> map = property->GetReceiverType(); | 5925 Handle<Map> map = property->GetReceiverType(); |
| 5942 Handle<String> name = property->key()->AsPropertyName(); | 5926 Handle<String> name = property->key()->AsPropertyName(); |
| 5943 HInstruction* store; | 5927 HInstruction* store; |
| 5944 if (map.is_null()) { | 5928 if (map.is_null()) { |
| 5945 // If we don't know the monomorphic type, do a generic store. | 5929 // If we don't know the monomorphic type, do a generic store. |
| 5946 CHECK_ALIVE(store = BuildStoreNamedGeneric(literal, name, value)); | 5930 CHECK_ALIVE(store = BuildStoreNamedGeneric(literal, name, value)); |
| 5947 } else { | 5931 } else { |
| (...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6059 AddInstruction(new(zone()) HPushArgument(AddInstruction( | 6043 AddInstruction(new(zone()) HPushArgument(AddInstruction( |
| 6060 new(zone()) HConstant(constants)))); | 6044 new(zone()) HConstant(constants)))); |
| 6061 | 6045 |
| 6062 Runtime::FunctionId function_id = (expr->depth() > 1) | 6046 Runtime::FunctionId function_id = (expr->depth() > 1) |
| 6063 ? Runtime::kCreateArrayLiteral : Runtime::kCreateArrayLiteralShallow; | 6047 ? Runtime::kCreateArrayLiteral : Runtime::kCreateArrayLiteralShallow; |
| 6064 literal = AddInstruction( | 6048 literal = AddInstruction( |
| 6065 new(zone()) HCallRuntime(context, | 6049 new(zone()) HCallRuntime(context, |
| 6066 isolate()->factory()->empty_string(), | 6050 isolate()->factory()->empty_string(), |
| 6067 Runtime::FunctionForId(function_id), | 6051 Runtime::FunctionForId(function_id), |
| 6068 3)); | 6052 3)); |
| 6053 |
| 6054 // De-opt if elements kind changed from boilerplate_elements_kind. |
| 6055 Handle<Map> map = Handle<Map>(original_boilerplate_object->map(), |
| 6056 isolate()); |
| 6057 AddInstruction(HCheckMaps::New(literal, map, zone())); |
| 6069 } | 6058 } |
| 6070 | 6059 |
| 6071 // The array is expected in the bailout environment during computation | 6060 // The array is expected in the bailout environment during computation |
| 6072 // of the property values and is the value of the entire expression. | 6061 // of the property values and is the value of the entire expression. |
| 6073 Push(literal); | 6062 Push(literal); |
| 6074 // The literal index is on the stack, too. | 6063 // The literal index is on the stack, too. |
| 6075 Push(AddInstruction(new(zone()) HConstant(expr->literal_index()))); | 6064 Push(AddInstruction(new(zone()) HConstant(expr->literal_index()))); |
| 6076 | 6065 |
| 6077 HInstruction* elements = NULL; | 6066 HInstruction* elements = NULL; |
| 6078 | 6067 |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6148 Map* transition = lookup->GetTransitionMapFromMap(*type); | 6137 Map* transition = lookup->GetTransitionMapFromMap(*type); |
| 6149 int descriptor = transition->LastAdded(); | 6138 int descriptor = transition->LastAdded(); |
| 6150 PropertyDetails details = | 6139 PropertyDetails details = |
| 6151 transition->instance_descriptors()->GetDetails(descriptor); | 6140 transition->instance_descriptors()->GetDetails(descriptor); |
| 6152 return details.representation(); | 6141 return details.representation(); |
| 6153 } | 6142 } |
| 6154 } | 6143 } |
| 6155 | 6144 |
| 6156 | 6145 |
| 6157 void HOptimizedGraphBuilder::AddCheckMap(HValue* object, Handle<Map> map) { | 6146 void HOptimizedGraphBuilder::AddCheckMap(HValue* object, Handle<Map> map) { |
| 6158 BuildCheckNonSmi(object); | 6147 BuildCheckHeapObject(object); |
| 6159 AddInstruction(HCheckMaps::New(object, map, zone())); | 6148 AddInstruction(HCheckMaps::New(object, map, zone())); |
| 6160 } | 6149 } |
| 6161 | 6150 |
| 6162 | 6151 |
| 6163 void HOptimizedGraphBuilder::AddCheckMapsWithTransitions(HValue* object, | 6152 void HOptimizedGraphBuilder::AddCheckMapsWithTransitions(HValue* object, |
| 6164 Handle<Map> map) { | 6153 Handle<Map> map) { |
| 6165 BuildCheckNonSmi(object); | 6154 BuildCheckHeapObject(object); |
| 6166 AddInstruction(HCheckMaps::NewWithTransitions(object, map, zone())); | 6155 AddInstruction(HCheckMaps::NewWithTransitions(object, map, zone())); |
| 6167 } | 6156 } |
| 6168 | 6157 |
| 6169 | 6158 |
| 6170 HInstruction* HOptimizedGraphBuilder::BuildStoreNamedField( | 6159 HInstruction* HOptimizedGraphBuilder::BuildStoreNamedField( |
| 6171 HValue* object, | 6160 HValue* object, |
| 6172 Handle<String> name, | 6161 Handle<String> name, |
| 6173 HValue* value, | 6162 HValue* value, |
| 6174 Handle<Map> map, | 6163 Handle<Map> map, |
| 6175 LookupResult* lookup) { | 6164 LookupResult* lookup) { |
| (...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6324 } else if (access.IsInobject() != new_access.IsInobject()) { | 6313 } else if (access.IsInobject() != new_access.IsInobject()) { |
| 6325 // In-objectness did not match. | 6314 // In-objectness did not match. |
| 6326 break; | 6315 break; |
| 6327 } | 6316 } |
| 6328 representation = representation.generalize(new_representation); | 6317 representation = representation.generalize(new_representation); |
| 6329 } | 6318 } |
| 6330 | 6319 |
| 6331 if (count != types->length()) return NULL; | 6320 if (count != types->length()) return NULL; |
| 6332 | 6321 |
| 6333 // Everything matched; can use monomorphic load. | 6322 // Everything matched; can use monomorphic load. |
| 6334 BuildCheckNonSmi(object); | 6323 BuildCheckHeapObject(object); |
| 6335 AddInstruction(HCheckMaps::New(object, types, zone())); | 6324 AddInstruction(HCheckMaps::New(object, types, zone())); |
| 6336 return BuildLoadNamedField(object, access, representation); | 6325 return BuildLoadNamedField(object, access, representation); |
| 6337 } | 6326 } |
| 6338 | 6327 |
| 6339 | 6328 |
| 6340 void HOptimizedGraphBuilder::HandlePolymorphicLoadNamedField( | 6329 void HOptimizedGraphBuilder::HandlePolymorphicLoadNamedField( |
| 6341 Property* expr, | 6330 Property* expr, |
| 6342 HValue* object, | 6331 HValue* object, |
| 6343 SmallMapList* types, | 6332 SmallMapList* types, |
| 6344 Handle<String> name) { | 6333 Handle<String> name) { |
| 6345 HInstruction* instr = TryLoadPolymorphicAsMonomorphic( | 6334 HInstruction* instr = TryLoadPolymorphicAsMonomorphic( |
| 6346 expr, object, types, name); | 6335 expr, object, types, name); |
| 6347 if (instr == NULL) { | 6336 if (instr == NULL) { |
| 6348 // Something did not match; must use a polymorphic load. | 6337 // Something did not match; must use a polymorphic load. |
| 6349 BuildCheckNonSmi(object); | 6338 BuildCheckHeapObject(object); |
| 6350 HValue* context = environment()->LookupContext(); | 6339 HValue* context = environment()->LookupContext(); |
| 6351 instr = new(zone()) HLoadNamedFieldPolymorphic( | 6340 instr = new(zone()) HLoadNamedFieldPolymorphic( |
| 6352 context, object, types, name, zone()); | 6341 context, object, types, name, zone()); |
| 6353 } | 6342 } |
| 6354 | 6343 |
| 6355 instr->set_position(expr->position()); | 6344 instr->set_position(expr->position()); |
| 6356 return ast_context()->ReturnInstruction(instr, expr->id()); | 6345 return ast_context()->ReturnInstruction(instr, expr->id()); |
| 6357 } | 6346 } |
| 6358 | 6347 |
| 6359 | 6348 |
| 6360 bool HOptimizedGraphBuilder::TryStorePolymorphicAsMonomorphic( | 6349 bool HOptimizedGraphBuilder::TryStorePolymorphicAsMonomorphic( |
| 6361 Assignment* expr, | 6350 int position, |
| 6351 BailoutId assignment_id, |
| 6362 HValue* object, | 6352 HValue* object, |
| 6363 HValue* value, | 6353 HValue* value, |
| 6364 SmallMapList* types, | 6354 SmallMapList* types, |
| 6365 Handle<String> name) { | 6355 Handle<String> name) { |
| 6366 // Use monomorphic store if property lookup results in the same field index | 6356 // Use monomorphic store if property lookup results in the same field index |
| 6367 // for all maps. Requires special map check on the set of all handled maps. | 6357 // for all maps. Requires special map check on the set of all handled maps. |
| 6368 if (types->length() > kMaxStorePolymorphism) return false; | 6358 if (types->length() > kMaxStorePolymorphism) return false; |
| 6369 | 6359 |
| 6370 // TODO(verwaest): Merge the checking logic with the code in | 6360 // TODO(verwaest): Merge the checking logic with the code in |
| 6371 // TryLoadPolymorphicAsMonomorphic. | 6361 // TryLoadPolymorphicAsMonomorphic. |
| (...skipping 22 matching lines...) Expand all Loading... |
| 6394 break; | 6384 break; |
| 6395 } else if (access.IsInobject() != new_access.IsInobject()) { | 6385 } else if (access.IsInobject() != new_access.IsInobject()) { |
| 6396 // In-objectness did not match. | 6386 // In-objectness did not match. |
| 6397 break; | 6387 break; |
| 6398 } | 6388 } |
| 6399 } | 6389 } |
| 6400 | 6390 |
| 6401 if (count != types->length()) return false; | 6391 if (count != types->length()) return false; |
| 6402 | 6392 |
| 6403 // Everything matched; can use monomorphic store. | 6393 // Everything matched; can use monomorphic store. |
| 6404 BuildCheckNonSmi(object); | 6394 BuildCheckHeapObject(object); |
| 6405 AddInstruction(HCheckMaps::New(object, types, zone())); | 6395 AddInstruction(HCheckMaps::New(object, types, zone())); |
| 6406 HInstruction* store; | 6396 HInstruction* store; |
| 6407 CHECK_ALIVE_OR_RETURN( | 6397 CHECK_ALIVE_OR_RETURN( |
| 6408 store = BuildStoreNamedField(object, name, value, types->at(0), &lookup), | 6398 store = BuildStoreNamedField( |
| 6399 object, name, value, types->at(count - 1), &lookup), |
| 6409 true); | 6400 true); |
| 6410 Push(value); | 6401 Push(value); |
| 6411 store->set_position(expr->position()); | 6402 store->set_position(position); |
| 6412 AddInstruction(store); | 6403 AddInstruction(store); |
| 6413 AddSimulate(expr->AssignmentId()); | 6404 AddSimulate(assignment_id); |
| 6414 ast_context()->ReturnValue(Pop()); | 6405 ast_context()->ReturnValue(Pop()); |
| 6415 return true; | 6406 return true; |
| 6416 } | 6407 } |
| 6417 | 6408 |
| 6418 | 6409 |
| 6419 void HOptimizedGraphBuilder::HandlePolymorphicStoreNamedField( | 6410 void HOptimizedGraphBuilder::HandlePolymorphicStoreNamedField( |
| 6420 Assignment* expr, | 6411 BailoutId id, |
| 6412 int position, |
| 6413 BailoutId assignment_id, |
| 6421 HValue* object, | 6414 HValue* object, |
| 6422 HValue* value, | 6415 HValue* value, |
| 6423 SmallMapList* types, | 6416 SmallMapList* types, |
| 6424 Handle<String> name) { | 6417 Handle<String> name) { |
| 6425 if (TryStorePolymorphicAsMonomorphic(expr, object, value, types, name)) { | 6418 if (TryStorePolymorphicAsMonomorphic( |
| 6419 position, assignment_id, object, value, types, name)) { |
| 6426 return; | 6420 return; |
| 6427 } | 6421 } |
| 6428 | 6422 |
| 6429 // TODO(ager): We should recognize when the prototype chains for different | 6423 // TODO(ager): We should recognize when the prototype chains for different |
| 6430 // maps are identical. In that case we can avoid repeatedly generating the | 6424 // maps are identical. In that case we can avoid repeatedly generating the |
| 6431 // same prototype map checks. | 6425 // same prototype map checks. |
| 6432 int count = 0; | 6426 int count = 0; |
| 6433 HBasicBlock* join = NULL; | 6427 HBasicBlock* join = NULL; |
| 6434 for (int i = 0; i < types->length() && count < kMaxStorePolymorphism; ++i) { | 6428 for (int i = 0; i < types->length() && count < kMaxStorePolymorphism; ++i) { |
| 6435 Handle<Map> map = types->at(i); | 6429 Handle<Map> map = types->at(i); |
| 6436 LookupResult lookup(isolate()); | 6430 LookupResult lookup(isolate()); |
| 6437 if (ComputeLoadStoreField(map, name, &lookup, true)) { | 6431 if (ComputeLoadStoreField(map, name, &lookup, true)) { |
| 6438 if (count == 0) { | 6432 if (count == 0) { |
| 6439 BuildCheckNonSmi(object); | 6433 BuildCheckHeapObject(object); |
| 6440 join = graph()->CreateBasicBlock(); | 6434 join = graph()->CreateBasicBlock(); |
| 6441 } | 6435 } |
| 6442 ++count; | 6436 ++count; |
| 6443 HBasicBlock* if_true = graph()->CreateBasicBlock(); | 6437 HBasicBlock* if_true = graph()->CreateBasicBlock(); |
| 6444 HBasicBlock* if_false = graph()->CreateBasicBlock(); | 6438 HBasicBlock* if_false = graph()->CreateBasicBlock(); |
| 6445 HCompareMap* compare = | 6439 HCompareMap* compare = |
| 6446 new(zone()) HCompareMap(object, map, if_true, if_false); | 6440 new(zone()) HCompareMap(object, map, if_true, if_false); |
| 6447 current_block()->Finish(compare); | 6441 current_block()->Finish(compare); |
| 6448 | 6442 |
| 6449 set_current_block(if_true); | 6443 set_current_block(if_true); |
| 6450 HInstruction* instr; | 6444 HInstruction* instr; |
| 6451 CHECK_ALIVE( | 6445 CHECK_ALIVE( |
| 6452 instr = BuildStoreNamedField(object, name, value, map, &lookup)); | 6446 instr = BuildStoreNamedField(object, name, value, map, &lookup)); |
| 6453 instr->set_position(expr->position()); | 6447 instr->set_position(position); |
| 6454 // Goto will add the HSimulate for the store. | 6448 // Goto will add the HSimulate for the store. |
| 6455 AddInstruction(instr); | 6449 AddInstruction(instr); |
| 6456 if (!ast_context()->IsEffect()) Push(value); | 6450 if (!ast_context()->IsEffect()) Push(value); |
| 6457 current_block()->Goto(join); | 6451 current_block()->Goto(join); |
| 6458 | 6452 |
| 6459 set_current_block(if_false); | 6453 set_current_block(if_false); |
| 6460 } | 6454 } |
| 6461 } | 6455 } |
| 6462 | 6456 |
| 6463 // Finish up. Unconditionally deoptimize if we've handled all the maps we | 6457 // Finish up. Unconditionally deoptimize if we've handled all the maps we |
| 6464 // know about and do not want to handle ones we've never seen. Otherwise | 6458 // know about and do not want to handle ones we've never seen. Otherwise |
| 6465 // use a generic IC. | 6459 // use a generic IC. |
| 6466 if (count == types->length() && FLAG_deoptimize_uncommon_cases) { | 6460 if (count == types->length() && FLAG_deoptimize_uncommon_cases) { |
| 6467 current_block()->FinishExitWithDeoptimization(HDeoptimize::kNoUses); | 6461 current_block()->FinishExitWithDeoptimization(HDeoptimize::kNoUses); |
| 6468 } else { | 6462 } else { |
| 6469 HInstruction* instr = BuildStoreNamedGeneric(object, name, value); | 6463 HInstruction* instr = BuildStoreNamedGeneric(object, name, value); |
| 6470 instr->set_position(expr->position()); | 6464 instr->set_position(position); |
| 6471 AddInstruction(instr); | 6465 AddInstruction(instr); |
| 6472 | 6466 |
| 6473 if (join != NULL) { | 6467 if (join != NULL) { |
| 6474 if (!ast_context()->IsEffect()) Push(value); | 6468 if (!ast_context()->IsEffect()) Push(value); |
| 6475 current_block()->Goto(join); | 6469 current_block()->Goto(join); |
| 6476 } else { | 6470 } else { |
| 6477 // The HSimulate for the store should not see the stored value in | 6471 // The HSimulate for the store should not see the stored value in |
| 6478 // effect contexts (it is not materialized at expr->id() in the | 6472 // effect contexts (it is not materialized at expr->id() in the |
| 6479 // unoptimized code). | 6473 // unoptimized code). |
| 6480 if (instr->HasObservableSideEffects()) { | 6474 if (instr->HasObservableSideEffects()) { |
| 6481 if (ast_context()->IsEffect()) { | 6475 if (ast_context()->IsEffect()) { |
| 6482 AddSimulate(expr->id(), REMOVABLE_SIMULATE); | 6476 AddSimulate(id, REMOVABLE_SIMULATE); |
| 6483 } else { | 6477 } else { |
| 6484 Push(value); | 6478 Push(value); |
| 6485 AddSimulate(expr->id(), REMOVABLE_SIMULATE); | 6479 AddSimulate(id, REMOVABLE_SIMULATE); |
| 6486 Drop(1); | 6480 Drop(1); |
| 6487 } | 6481 } |
| 6488 } | 6482 } |
| 6489 return ast_context()->ReturnValue(value); | 6483 return ast_context()->ReturnValue(value); |
| 6490 } | 6484 } |
| 6491 } | 6485 } |
| 6492 | 6486 |
| 6493 ASSERT(join != NULL); | 6487 ASSERT(join != NULL); |
| 6494 join->SetJoinId(expr->id()); | 6488 join->SetJoinId(id); |
| 6495 set_current_block(join); | 6489 set_current_block(join); |
| 6496 if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop()); | 6490 if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop()); |
| 6497 } | 6491 } |
| 6498 | 6492 |
| 6499 | 6493 |
| 6500 void HOptimizedGraphBuilder::HandlePropertyAssignment(Assignment* expr) { | 6494 void HOptimizedGraphBuilder::HandlePropertyAssignment(Assignment* expr) { |
| 6501 Property* prop = expr->target()->AsProperty(); | 6495 Property* prop = expr->target()->AsProperty(); |
| 6502 ASSERT(prop != NULL); | 6496 ASSERT(prop != NULL); |
| 6503 CHECK_ALIVE(VisitForValue(prop->obj())); | 6497 CHECK_ALIVE(VisitForValue(prop->obj())); |
| 6504 | 6498 |
| 6505 if (prop->key()->IsPropertyName()) { | 6499 if (prop->key()->IsPropertyName()) { |
| 6506 // Named store. | 6500 // Named store. |
| 6507 CHECK_ALIVE(VisitForValue(expr->value())); | 6501 CHECK_ALIVE(VisitForValue(expr->value())); |
| 6508 HValue* value = environment()->ExpressionStackAt(0); | 6502 HValue* value = environment()->ExpressionStackAt(0); |
| 6509 HValue* object = environment()->ExpressionStackAt(1); | 6503 HValue* object = environment()->ExpressionStackAt(1); |
| 6510 | 6504 |
| 6511 Literal* key = prop->key()->AsLiteral(); | 6505 if (expr->IsUninitialized()) AddSoftDeoptimize(); |
| 6512 Handle<String> name = Handle<String>::cast(key->handle()); | 6506 return BuildStoreNamed(expr, expr->id(), expr->position(), |
| 6513 ASSERT(!name.is_null()); | 6507 expr->AssignmentId(), prop, object, value); |
| 6514 | |
| 6515 HInstruction* instr = NULL; | |
| 6516 SmallMapList* types = expr->GetReceiverTypes(); | |
| 6517 bool monomorphic = expr->IsMonomorphic(); | |
| 6518 Handle<Map> map; | |
| 6519 if (monomorphic) { | |
| 6520 map = types->first(); | |
| 6521 if (map->is_dictionary_map()) monomorphic = false; | |
| 6522 } | |
| 6523 if (monomorphic) { | |
| 6524 Handle<JSFunction> setter; | |
| 6525 Handle<JSObject> holder; | |
| 6526 if (LookupSetter(map, name, &setter, &holder)) { | |
| 6527 AddCheckConstantFunction(holder, object, map); | |
| 6528 if (FLAG_inline_accessors && TryInlineSetter(setter, expr, value)) { | |
| 6529 return; | |
| 6530 } | |
| 6531 Drop(2); | |
| 6532 AddInstruction(new(zone()) HPushArgument(object)); | |
| 6533 AddInstruction(new(zone()) HPushArgument(value)); | |
| 6534 instr = new(zone()) HCallConstantFunction(setter, 2); | |
| 6535 } else { | |
| 6536 Drop(2); | |
| 6537 CHECK_ALIVE(instr = BuildStoreNamedMonomorphic(object, | |
| 6538 name, | |
| 6539 value, | |
| 6540 map)); | |
| 6541 } | |
| 6542 | |
| 6543 } else if (types != NULL && types->length() > 1) { | |
| 6544 Drop(2); | |
| 6545 return HandlePolymorphicStoreNamedField(expr, object, value, types, name); | |
| 6546 } else { | |
| 6547 Drop(2); | |
| 6548 instr = BuildStoreNamedGeneric(object, name, value); | |
| 6549 } | |
| 6550 | |
| 6551 Push(value); | |
| 6552 instr->set_position(expr->position()); | |
| 6553 AddInstruction(instr); | |
| 6554 if (instr->HasObservableSideEffects()) { | |
| 6555 AddSimulate(expr->AssignmentId(), REMOVABLE_SIMULATE); | |
| 6556 } | |
| 6557 return ast_context()->ReturnValue(Pop()); | |
| 6558 | |
| 6559 } else { | 6508 } else { |
| 6560 // Keyed store. | 6509 // Keyed store. |
| 6561 CHECK_ALIVE(VisitForValue(prop->key())); | 6510 CHECK_ALIVE(VisitForValue(prop->key())); |
| 6562 CHECK_ALIVE(VisitForValue(expr->value())); | 6511 CHECK_ALIVE(VisitForValue(expr->value())); |
| 6563 HValue* value = environment()->ExpressionStackAt(0); | 6512 HValue* value = environment()->ExpressionStackAt(0); |
| 6564 HValue* key = environment()->ExpressionStackAt(1); | 6513 HValue* key = environment()->ExpressionStackAt(1); |
| 6565 HValue* object = environment()->ExpressionStackAt(2); | 6514 HValue* object = environment()->ExpressionStackAt(2); |
| 6566 bool has_side_effects = false; | 6515 bool has_side_effects = false; |
| 6567 HandleKeyedElementAccess(object, key, value, expr, expr->AssignmentId(), | 6516 HandleKeyedElementAccess(object, key, value, expr, expr->AssignmentId(), |
| 6568 expr->position(), | 6517 expr->position(), |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6607 value, | 6556 value, |
| 6608 function_strict_mode_flag()); | 6557 function_strict_mode_flag()); |
| 6609 instr->set_position(position); | 6558 instr->set_position(position); |
| 6610 AddInstruction(instr); | 6559 AddInstruction(instr); |
| 6611 ASSERT(instr->HasObservableSideEffects()); | 6560 ASSERT(instr->HasObservableSideEffects()); |
| 6612 AddSimulate(ast_id, REMOVABLE_SIMULATE); | 6561 AddSimulate(ast_id, REMOVABLE_SIMULATE); |
| 6613 } | 6562 } |
| 6614 } | 6563 } |
| 6615 | 6564 |
| 6616 | 6565 |
| 6566 void HOptimizedGraphBuilder::BuildStoreNamed(Expression* expr, |
| 6567 BailoutId id, |
| 6568 int position, |
| 6569 BailoutId assignment_id, |
| 6570 Property* prop, |
| 6571 HValue* object, |
| 6572 HValue* value) { |
| 6573 Literal* key = prop->key()->AsLiteral(); |
| 6574 Handle<String> name = Handle<String>::cast(key->value()); |
| 6575 ASSERT(!name.is_null()); |
| 6576 |
| 6577 HInstruction* instr = NULL; |
| 6578 SmallMapList* types = expr->GetReceiverTypes(); |
| 6579 bool monomorphic = expr->IsMonomorphic(); |
| 6580 Handle<Map> map; |
| 6581 if (monomorphic) { |
| 6582 map = types->first(); |
| 6583 if (map->is_dictionary_map()) monomorphic = false; |
| 6584 } |
| 6585 if (monomorphic) { |
| 6586 Handle<JSFunction> setter; |
| 6587 Handle<JSObject> holder; |
| 6588 if (LookupSetter(map, name, &setter, &holder)) { |
| 6589 AddCheckConstantFunction(holder, object, map); |
| 6590 if (FLAG_inline_accessors && |
| 6591 TryInlineSetter(setter, id, assignment_id, value)) { |
| 6592 return; |
| 6593 } |
| 6594 Drop(2); |
| 6595 AddInstruction(new(zone()) HPushArgument(object)); |
| 6596 AddInstruction(new(zone()) HPushArgument(value)); |
| 6597 instr = new(zone()) HCallConstantFunction(setter, 2); |
| 6598 } else { |
| 6599 Drop(2); |
| 6600 CHECK_ALIVE(instr = BuildStoreNamedMonomorphic(object, |
| 6601 name, |
| 6602 value, |
| 6603 map)); |
| 6604 } |
| 6605 |
| 6606 } else if (types != NULL && types->length() > 1) { |
| 6607 Drop(2); |
| 6608 return HandlePolymorphicStoreNamedField( |
| 6609 id, position, assignment_id, object, value, types, name); |
| 6610 } else { |
| 6611 Drop(2); |
| 6612 instr = BuildStoreNamedGeneric(object, name, value); |
| 6613 } |
| 6614 |
| 6615 Push(value); |
| 6616 instr->set_position(position); |
| 6617 AddInstruction(instr); |
| 6618 if (instr->HasObservableSideEffects()) { |
| 6619 AddSimulate(assignment_id, REMOVABLE_SIMULATE); |
| 6620 } |
| 6621 return ast_context()->ReturnValue(Pop()); |
| 6622 } |
| 6623 |
| 6624 |
| 6617 void HOptimizedGraphBuilder::HandleCompoundAssignment(Assignment* expr) { | 6625 void HOptimizedGraphBuilder::HandleCompoundAssignment(Assignment* expr) { |
| 6618 Expression* target = expr->target(); | 6626 Expression* target = expr->target(); |
| 6619 VariableProxy* proxy = target->AsVariableProxy(); | 6627 VariableProxy* proxy = target->AsVariableProxy(); |
| 6620 Property* prop = target->AsProperty(); | 6628 Property* prop = target->AsProperty(); |
| 6621 ASSERT(proxy == NULL || prop == NULL); | 6629 ASSERT(proxy == NULL || prop == NULL); |
| 6622 | 6630 |
| 6623 // We have a second position recorded in the FullCodeGenerator to have | 6631 // We have a second position recorded in the FullCodeGenerator to have |
| 6624 // type feedback for the binary operation. | 6632 // type feedback for the binary operation. |
| 6625 BinaryOperation* operation = expr->binary_operation(); | 6633 BinaryOperation* operation = expr->binary_operation(); |
| 6626 | 6634 |
| (...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6733 CHECK_ALIVE(VisitForValue(expr->value())); | 6741 CHECK_ALIVE(VisitForValue(expr->value())); |
| 6734 HValue* right = Pop(); | 6742 HValue* right = Pop(); |
| 6735 HValue* left = Pop(); | 6743 HValue* left = Pop(); |
| 6736 | 6744 |
| 6737 HInstruction* instr = BuildBinaryOperation(operation, left, right); | 6745 HInstruction* instr = BuildBinaryOperation(operation, left, right); |
| 6738 PushAndAdd(instr); | 6746 PushAndAdd(instr); |
| 6739 if (instr->HasObservableSideEffects()) { | 6747 if (instr->HasObservableSideEffects()) { |
| 6740 AddSimulate(operation->id(), REMOVABLE_SIMULATE); | 6748 AddSimulate(operation->id(), REMOVABLE_SIMULATE); |
| 6741 } | 6749 } |
| 6742 | 6750 |
| 6743 HInstruction* store; | 6751 return BuildStoreNamed(prop, expr->id(), expr->position(), |
| 6744 if (!monomorphic || map->is_observed()) { | 6752 expr->AssignmentId(), prop, object, instr); |
| 6745 // If we don't know the monomorphic type, do a generic store. | |
| 6746 CHECK_ALIVE(store = BuildStoreNamedGeneric(object, name, instr)); | |
| 6747 } else { | |
| 6748 Handle<JSFunction> setter; | |
| 6749 Handle<JSObject> holder; | |
| 6750 if (LookupSetter(map, name, &setter, &holder)) { | |
| 6751 store = BuildCallSetter(object, instr, map, setter, holder); | |
| 6752 } else { | |
| 6753 CHECK_ALIVE(store = BuildStoreNamedMonomorphic(object, | |
| 6754 name, | |
| 6755 instr, | |
| 6756 map)); | |
| 6757 } | |
| 6758 } | |
| 6759 AddInstruction(store); | |
| 6760 // Drop the simulated receiver and value. Return the value. | |
| 6761 Drop(2); | |
| 6762 Push(instr); | |
| 6763 if (store->HasObservableSideEffects()) { | |
| 6764 AddSimulate(expr->AssignmentId(), REMOVABLE_SIMULATE); | |
| 6765 } | |
| 6766 return ast_context()->ReturnValue(Pop()); | |
| 6767 | |
| 6768 } else { | 6753 } else { |
| 6769 // Keyed property. | 6754 // Keyed property. |
| 6770 CHECK_ALIVE(VisitForValue(prop->obj())); | 6755 CHECK_ALIVE(VisitForValue(prop->obj())); |
| 6771 CHECK_ALIVE(VisitForValue(prop->key())); | 6756 CHECK_ALIVE(VisitForValue(prop->key())); |
| 6772 HValue* obj = environment()->ExpressionStackAt(1); | 6757 HValue* obj = environment()->ExpressionStackAt(1); |
| 6773 HValue* key = environment()->ExpressionStackAt(0); | 6758 HValue* key = environment()->ExpressionStackAt(0); |
| 6774 | 6759 |
| 6775 bool has_side_effects = false; | 6760 bool has_side_effects = false; |
| 6776 HValue* load = HandleKeyedElementAccess( | 6761 HValue* load = HandleKeyedElementAccess( |
| 6777 obj, key, NULL, prop, prop->LoadId(), RelocInfo::kNoPosition, | 6762 obj, key, NULL, prop, prop->LoadId(), RelocInfo::kNoPosition, |
| (...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6983 return field; | 6968 return field; |
| 6984 } | 6969 } |
| 6985 | 6970 |
| 6986 | 6971 |
| 6987 HInstruction* HOptimizedGraphBuilder::BuildLoadNamedGeneric( | 6972 HInstruction* HOptimizedGraphBuilder::BuildLoadNamedGeneric( |
| 6988 HValue* object, | 6973 HValue* object, |
| 6989 Handle<String> name, | 6974 Handle<String> name, |
| 6990 Property* expr) { | 6975 Property* expr) { |
| 6991 if (expr->IsUninitialized()) { | 6976 if (expr->IsUninitialized()) { |
| 6992 AddSoftDeoptimize(); | 6977 AddSoftDeoptimize(); |
| 6993 } else { | |
| 6994 // OS::DebugBreak(); | |
| 6995 } | 6978 } |
| 6996 HValue* context = environment()->LookupContext(); | 6979 HValue* context = environment()->LookupContext(); |
| 6997 return new(zone()) HLoadNamedGeneric(context, object, name); | 6980 return new(zone()) HLoadNamedGeneric(context, object, name); |
| 6998 } | 6981 } |
| 6999 | 6982 |
| 7000 | 6983 |
| 7001 HInstruction* HOptimizedGraphBuilder::BuildCallGetter( | 6984 HInstruction* HOptimizedGraphBuilder::BuildCallGetter( |
| 7002 HValue* object, | 6985 HValue* object, |
| 7003 Handle<Map> map, | 6986 Handle<Map> map, |
| 7004 Handle<JSFunction> getter, | 6987 Handle<JSFunction> getter, |
| (...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7174 HValue* object, | 7157 HValue* object, |
| 7175 HValue* key, | 7158 HValue* key, |
| 7176 HValue* val, | 7159 HValue* val, |
| 7177 Expression* prop, | 7160 Expression* prop, |
| 7178 BailoutId ast_id, | 7161 BailoutId ast_id, |
| 7179 int position, | 7162 int position, |
| 7180 bool is_store, | 7163 bool is_store, |
| 7181 KeyedAccessStoreMode store_mode, | 7164 KeyedAccessStoreMode store_mode, |
| 7182 bool* has_side_effects) { | 7165 bool* has_side_effects) { |
| 7183 *has_side_effects = false; | 7166 *has_side_effects = false; |
| 7184 BuildCheckNonSmi(object); | 7167 BuildCheckHeapObject(object); |
| 7185 SmallMapList* maps = prop->GetReceiverTypes(); | 7168 SmallMapList* maps = prop->GetReceiverTypes(); |
| 7186 bool todo_external_array = false; | 7169 bool todo_external_array = false; |
| 7187 | 7170 |
| 7188 if (!is_store) { | 7171 if (!is_store) { |
| 7189 HInstruction* consolidated_load = | 7172 HInstruction* consolidated_load = |
| 7190 TryBuildConsolidatedElementLoad(object, key, val, maps); | 7173 TryBuildConsolidatedElementLoad(object, key, val, maps); |
| 7191 if (consolidated_load != NULL) { | 7174 if (consolidated_load != NULL) { |
| 7192 *has_side_effects |= consolidated_load->HasObservableSideEffects(); | 7175 *has_side_effects |= consolidated_load->HasObservableSideEffects(); |
| 7193 if (position != RelocInfo::kNoPosition) { | 7176 if (position != RelocInfo::kNoPosition) { |
| 7194 consolidated_load->set_position(position); | 7177 consolidated_load->set_position(position); |
| (...skipping 204 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7399 bool* has_side_effects) { | 7382 bool* has_side_effects) { |
| 7400 ASSERT(!expr->IsPropertyName()); | 7383 ASSERT(!expr->IsPropertyName()); |
| 7401 HInstruction* instr = NULL; | 7384 HInstruction* instr = NULL; |
| 7402 if (expr->IsMonomorphic()) { | 7385 if (expr->IsMonomorphic()) { |
| 7403 Handle<Map> map = expr->GetMonomorphicReceiverType(); | 7386 Handle<Map> map = expr->GetMonomorphicReceiverType(); |
| 7404 if (map->has_slow_elements_kind()) { | 7387 if (map->has_slow_elements_kind()) { |
| 7405 instr = is_store ? BuildStoreKeyedGeneric(obj, key, val) | 7388 instr = is_store ? BuildStoreKeyedGeneric(obj, key, val) |
| 7406 : BuildLoadKeyedGeneric(obj, key); | 7389 : BuildLoadKeyedGeneric(obj, key); |
| 7407 AddInstruction(instr); | 7390 AddInstruction(instr); |
| 7408 } else { | 7391 } else { |
| 7409 BuildCheckNonSmi(obj); | 7392 BuildCheckHeapObject(obj); |
| 7410 instr = BuildMonomorphicElementAccess( | 7393 instr = BuildMonomorphicElementAccess( |
| 7411 obj, key, val, NULL, map, is_store, expr->GetStoreMode()); | 7394 obj, key, val, NULL, map, is_store, expr->GetStoreMode()); |
| 7412 } | 7395 } |
| 7413 } else if (expr->GetReceiverTypes() != NULL && | 7396 } else if (expr->GetReceiverTypes() != NULL && |
| 7414 !expr->GetReceiverTypes()->is_empty()) { | 7397 !expr->GetReceiverTypes()->is_empty()) { |
| 7415 return HandlePolymorphicElementAccess( | 7398 return HandlePolymorphicElementAccess( |
| 7416 obj, key, val, expr, ast_id, position, is_store, | 7399 obj, key, val, expr, ast_id, position, is_store, |
| 7417 expr->GetStoreMode(), has_side_effects); | 7400 expr->GetStoreMode(), has_side_effects); |
| 7418 } else { | 7401 } else { |
| 7419 if (is_store) { | 7402 if (is_store) { |
| (...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7531 ASSERT(current_block() != NULL); | 7514 ASSERT(current_block() != NULL); |
| 7532 ASSERT(current_block()->HasPredecessor()); | 7515 ASSERT(current_block()->HasPredecessor()); |
| 7533 | 7516 |
| 7534 if (TryArgumentsAccess(expr)) return; | 7517 if (TryArgumentsAccess(expr)) return; |
| 7535 | 7518 |
| 7536 CHECK_ALIVE(VisitForValue(expr->obj())); | 7519 CHECK_ALIVE(VisitForValue(expr->obj())); |
| 7537 | 7520 |
| 7538 HInstruction* instr = NULL; | 7521 HInstruction* instr = NULL; |
| 7539 if (expr->IsStringLength()) { | 7522 if (expr->IsStringLength()) { |
| 7540 HValue* string = Pop(); | 7523 HValue* string = Pop(); |
| 7541 BuildCheckNonSmi(string); | 7524 BuildCheckHeapObject(string); |
| 7542 AddInstruction(HCheckInstanceType::NewIsString(string, zone())); | 7525 AddInstruction(HCheckInstanceType::NewIsString(string, zone())); |
| 7543 instr = HStringLength::New(zone(), string); | 7526 instr = HStringLength::New(zone(), string); |
| 7544 } else if (expr->IsStringAccess()) { | 7527 } else if (expr->IsStringAccess()) { |
| 7545 CHECK_ALIVE(VisitForValue(expr->key())); | 7528 CHECK_ALIVE(VisitForValue(expr->key())); |
| 7546 HValue* index = Pop(); | 7529 HValue* index = Pop(); |
| 7547 HValue* string = Pop(); | 7530 HValue* string = Pop(); |
| 7548 HValue* context = environment()->LookupContext(); | 7531 HValue* context = environment()->LookupContext(); |
| 7549 HInstruction* char_code = | 7532 HInstruction* char_code = |
| 7550 BuildStringCharCodeAt(context, string, index); | 7533 BuildStringCharCodeAt(context, string, index); |
| 7551 AddInstruction(char_code); | 7534 AddInstruction(char_code); |
| 7552 instr = HStringCharFromCode::New(zone(), context, char_code); | 7535 instr = HStringCharFromCode::New(zone(), context, char_code); |
| 7553 | 7536 |
| 7554 } else if (expr->IsFunctionPrototype()) { | 7537 } else if (expr->IsFunctionPrototype()) { |
| 7555 HValue* function = Pop(); | 7538 HValue* function = Pop(); |
| 7556 BuildCheckNonSmi(function); | 7539 BuildCheckHeapObject(function); |
| 7557 instr = new(zone()) HLoadFunctionPrototype(function); | 7540 instr = new(zone()) HLoadFunctionPrototype(function); |
| 7558 | 7541 |
| 7559 } else if (expr->key()->IsPropertyName()) { | 7542 } else if (expr->key()->IsPropertyName()) { |
| 7560 Handle<String> name = expr->key()->AsLiteral()->AsPropertyName(); | 7543 Handle<String> name = expr->key()->AsLiteral()->AsPropertyName(); |
| 7561 SmallMapList* types = expr->GetReceiverTypes(); | 7544 SmallMapList* types = expr->GetReceiverTypes(); |
| 7562 HValue* object = Top(); | 7545 HValue* object = Top(); |
| 7563 | 7546 |
| 7564 Handle<Map> map; | 7547 Handle<Map> map; |
| 7565 bool monomorphic = false; | 7548 bool monomorphic = false; |
| 7566 if (expr->IsMonomorphic()) { | 7549 if (expr->IsMonomorphic()) { |
| (...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7720 HBasicBlock* empty_smi_block = graph()->CreateBasicBlock(); | 7703 HBasicBlock* empty_smi_block = graph()->CreateBasicBlock(); |
| 7721 HBasicBlock* not_smi_block = graph()->CreateBasicBlock(); | 7704 HBasicBlock* not_smi_block = graph()->CreateBasicBlock(); |
| 7722 number_block = graph()->CreateBasicBlock(); | 7705 number_block = graph()->CreateBasicBlock(); |
| 7723 HIsSmiAndBranch* smicheck = new(zone()) HIsSmiAndBranch(receiver); | 7706 HIsSmiAndBranch* smicheck = new(zone()) HIsSmiAndBranch(receiver); |
| 7724 smicheck->SetSuccessorAt(0, empty_smi_block); | 7707 smicheck->SetSuccessorAt(0, empty_smi_block); |
| 7725 smicheck->SetSuccessorAt(1, not_smi_block); | 7708 smicheck->SetSuccessorAt(1, not_smi_block); |
| 7726 current_block()->Finish(smicheck); | 7709 current_block()->Finish(smicheck); |
| 7727 empty_smi_block->Goto(number_block); | 7710 empty_smi_block->Goto(number_block); |
| 7728 set_current_block(not_smi_block); | 7711 set_current_block(not_smi_block); |
| 7729 } else { | 7712 } else { |
| 7730 BuildCheckNonSmi(receiver); | 7713 BuildCheckHeapObject(receiver); |
| 7731 } | 7714 } |
| 7732 } | 7715 } |
| 7733 HBasicBlock* if_true = graph()->CreateBasicBlock(); | 7716 HBasicBlock* if_true = graph()->CreateBasicBlock(); |
| 7734 HBasicBlock* if_false = graph()->CreateBasicBlock(); | 7717 HBasicBlock* if_false = graph()->CreateBasicBlock(); |
| 7735 HUnaryControlInstruction* compare; | 7718 HUnaryControlInstruction* compare; |
| 7736 | 7719 |
| 7737 if (handle_smi && map.is_identical_to(number_marker_map)) { | 7720 if (handle_smi && map.is_identical_to(number_marker_map)) { |
| 7738 compare = new(zone()) HCompareMap( | 7721 compare = new(zone()) HCompareMap( |
| 7739 receiver, heap_number_map, if_true, if_false); | 7722 receiver, heap_number_map, if_true, if_false); |
| 7740 map = initial_number_map; | 7723 map = initial_number_map; |
| (...skipping 479 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8220 getter, | 8203 getter, |
| 8221 0, | 8204 0, |
| 8222 NULL, | 8205 NULL, |
| 8223 prop->id(), | 8206 prop->id(), |
| 8224 prop->LoadId(), | 8207 prop->LoadId(), |
| 8225 GETTER_CALL_RETURN); | 8208 GETTER_CALL_RETURN); |
| 8226 } | 8209 } |
| 8227 | 8210 |
| 8228 | 8211 |
| 8229 bool HOptimizedGraphBuilder::TryInlineSetter(Handle<JSFunction> setter, | 8212 bool HOptimizedGraphBuilder::TryInlineSetter(Handle<JSFunction> setter, |
| 8230 Assignment* assignment, | 8213 BailoutId id, |
| 8214 BailoutId assignment_id, |
| 8231 HValue* implicit_return_value) { | 8215 HValue* implicit_return_value) { |
| 8232 return TryInline(CALL_AS_METHOD, | 8216 return TryInline(CALL_AS_METHOD, |
| 8233 setter, | 8217 setter, |
| 8234 1, | 8218 1, |
| 8235 implicit_return_value, | 8219 implicit_return_value, |
| 8236 assignment->id(), | 8220 id, assignment_id, |
| 8237 assignment->AssignmentId(), | |
| 8238 SETTER_CALL_RETURN); | 8221 SETTER_CALL_RETURN); |
| 8239 } | 8222 } |
| 8240 | 8223 |
| 8241 | 8224 |
| 8242 bool HOptimizedGraphBuilder::TryInlineApply(Handle<JSFunction> function, | 8225 bool HOptimizedGraphBuilder::TryInlineApply(Handle<JSFunction> function, |
| 8243 Call* expr, | 8226 Call* expr, |
| 8244 int arguments_count) { | 8227 int arguments_count) { |
| 8245 return TryInline(CALL_AS_METHOD, | 8228 return TryInline(CALL_AS_METHOD, |
| 8246 function, | 8229 function, |
| 8247 arguments_count, | 8230 arguments_count, |
| (...skipping 574 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8822 | 8805 |
| 8823 call->set_position(expr->position()); | 8806 call->set_position(expr->position()); |
| 8824 return ast_context()->ReturnInstruction(call, expr->id()); | 8807 return ast_context()->ReturnInstruction(call, expr->id()); |
| 8825 } | 8808 } |
| 8826 | 8809 |
| 8827 | 8810 |
| 8828 // Checks whether allocation using the given constructor can be inlined. | 8811 // Checks whether allocation using the given constructor can be inlined. |
| 8829 static bool IsAllocationInlineable(Handle<JSFunction> constructor) { | 8812 static bool IsAllocationInlineable(Handle<JSFunction> constructor) { |
| 8830 return constructor->has_initial_map() && | 8813 return constructor->has_initial_map() && |
| 8831 constructor->initial_map()->instance_type() == JS_OBJECT_TYPE && | 8814 constructor->initial_map()->instance_type() == JS_OBJECT_TYPE && |
| 8832 constructor->initial_map()->instance_size() < HAllocate::kMaxInlineSize && | 8815 constructor->initial_map()->instance_size() < HAllocateObject::kMaxSize; |
| 8833 constructor->initial_map()->InitialPropertiesLength() == 0; | |
| 8834 } | 8816 } |
| 8835 | 8817 |
| 8836 | 8818 |
| 8837 void HOptimizedGraphBuilder::VisitCallNew(CallNew* expr) { | 8819 void HOptimizedGraphBuilder::VisitCallNew(CallNew* expr) { |
| 8838 ASSERT(!HasStackOverflow()); | 8820 ASSERT(!HasStackOverflow()); |
| 8839 ASSERT(current_block() != NULL); | 8821 ASSERT(current_block() != NULL); |
| 8840 ASSERT(current_block()->HasPredecessor()); | 8822 ASSERT(current_block()->HasPredecessor()); |
| 8841 int argument_count = expr->arguments()->length() + 1; // Plus constructor. | 8823 int argument_count = expr->arguments()->length() + 1; // Plus constructor. |
| 8842 HValue* context = environment()->LookupContext(); | 8824 HValue* context = environment()->LookupContext(); |
| 8843 Factory* factory = isolate()->factory(); | |
| 8844 | 8825 |
| 8845 if (FLAG_inline_construct && | 8826 if (FLAG_inline_construct && |
| 8846 expr->IsMonomorphic() && | 8827 expr->IsMonomorphic() && |
| 8847 IsAllocationInlineable(expr->target())) { | 8828 IsAllocationInlineable(expr->target())) { |
| 8848 // The constructor function is on the stack in the unoptimized code | 8829 // The constructor function is on the stack in the unoptimized code |
| 8849 // during evaluation of the arguments. | 8830 // during evaluation of the arguments. |
| 8850 CHECK_ALIVE(VisitForValue(expr->expression())); | 8831 CHECK_ALIVE(VisitForValue(expr->expression())); |
| 8851 HValue* function = Top(); | 8832 HValue* function = Top(); |
| 8852 CHECK_ALIVE(VisitExpressions(expr->arguments())); | 8833 CHECK_ALIVE(VisitExpressions(expr->arguments())); |
| 8853 Handle<JSFunction> constructor = expr->target(); | 8834 Handle<JSFunction> constructor = expr->target(); |
| 8854 HValue* check = AddInstruction( | 8835 HValue* check = AddInstruction( |
| 8855 new(zone()) HCheckFunction(function, constructor)); | 8836 new(zone()) HCheckFunction(function, constructor)); |
| 8856 | 8837 |
| 8857 // Force completion of inobject slack tracking before generating | 8838 // Force completion of inobject slack tracking before generating |
| 8858 // allocation code to finalize instance size. | 8839 // allocation code to finalize instance size. |
| 8859 if (constructor->shared()->IsInobjectSlackTrackingInProgress()) { | 8840 if (constructor->shared()->IsInobjectSlackTrackingInProgress()) { |
| 8860 constructor->shared()->CompleteInobjectSlackTracking(); | 8841 constructor->shared()->CompleteInobjectSlackTracking(); |
| 8861 } | 8842 } |
| 8862 | 8843 |
| 8863 // Calculate instance size from initial map of constructor. | 8844 // Replace the constructor function with a newly allocated receiver. |
| 8864 ASSERT(constructor->has_initial_map()); | 8845 HInstruction* receiver = new(zone()) HAllocateObject(context, constructor); |
| 8865 Handle<Map> initial_map(constructor->initial_map()); | 8846 // Index of the receiver from the top of the expression stack. |
| 8866 int instance_size = initial_map->instance_size(); | |
| 8867 ASSERT(initial_map->InitialPropertiesLength() == 0); | |
| 8868 | |
| 8869 // Allocate an instance of the implicit receiver object. | |
| 8870 HValue* size_in_bytes = | |
| 8871 AddInstruction(new(zone()) HConstant(instance_size)); | |
| 8872 | |
| 8873 HAllocate::Flags flags = HAllocate::DefaultFlags(); | |
| 8874 if (FLAG_pretenuring_call_new && | |
| 8875 isolate()->heap()->ShouldGloballyPretenure()) { | |
| 8876 flags = static_cast<HAllocate::Flags>( | |
| 8877 flags | HAllocate::CAN_ALLOCATE_IN_OLD_POINTER_SPACE); | |
| 8878 } | |
| 8879 | |
| 8880 HInstruction* receiver = | |
| 8881 AddInstruction(new(zone()) HAllocate(context, | |
| 8882 size_in_bytes, | |
| 8883 HType::JSObject(), | |
| 8884 flags)); | |
| 8885 HAllocate::cast(receiver)->set_known_initial_map(initial_map); | |
| 8886 | |
| 8887 // Load the initial map from the constructor. | |
| 8888 HValue* constructor_value = | |
| 8889 AddInstruction(new(zone()) HConstant(constructor)); | |
| 8890 HValue* initial_map_value = | |
| 8891 AddLoad(constructor_value, HObjectAccess::ForJSObjectOffset( | |
| 8892 JSFunction::kPrototypeOrInitialMapOffset)); | |
| 8893 | |
| 8894 // Initialize map and fields of the newly allocated object. | |
| 8895 { NoObservableSideEffectsScope no_effects(this); | |
| 8896 ASSERT(initial_map->instance_type() == JS_OBJECT_TYPE); | |
| 8897 AddStore(receiver, | |
| 8898 HObjectAccess::ForJSObjectOffset(JSObject::kMapOffset), | |
| 8899 initial_map_value); | |
| 8900 HValue* empty_fixed_array = | |
| 8901 AddInstruction(new(zone()) HConstant(factory->empty_fixed_array())); | |
| 8902 AddStore(receiver, | |
| 8903 HObjectAccess::ForJSObjectOffset(JSObject::kPropertiesOffset), | |
| 8904 empty_fixed_array); | |
| 8905 AddStore(receiver, | |
| 8906 HObjectAccess::ForJSObjectOffset(JSObject::kElementsOffset), | |
| 8907 empty_fixed_array); | |
| 8908 if (initial_map->inobject_properties() != 0) { | |
| 8909 HConstant* undefined = graph()->GetConstantUndefined(); | |
| 8910 for (int i = 0; i < initial_map->inobject_properties(); i++) { | |
| 8911 int property_offset = JSObject::kHeaderSize + i * kPointerSize; | |
| 8912 AddStore(receiver, | |
| 8913 HObjectAccess::ForJSObjectOffset(property_offset), | |
| 8914 undefined); | |
| 8915 } | |
| 8916 } | |
| 8917 } | |
| 8918 | |
| 8919 // Replace the constructor function with a newly allocated receiver using | |
| 8920 // the index of the receiver from the top of the expression stack. | |
| 8921 const int receiver_index = argument_count - 1; | 8847 const int receiver_index = argument_count - 1; |
| 8848 AddInstruction(receiver); |
| 8922 ASSERT(environment()->ExpressionStackAt(receiver_index) == function); | 8849 ASSERT(environment()->ExpressionStackAt(receiver_index) == function); |
| 8923 environment()->SetExpressionStackAt(receiver_index, receiver); | 8850 environment()->SetExpressionStackAt(receiver_index, receiver); |
| 8924 | 8851 |
| 8925 if (TryInlineConstruct(expr, receiver)) return; | 8852 if (TryInlineConstruct(expr, receiver)) return; |
| 8926 | 8853 |
| 8927 // TODO(mstarzinger): For now we remove the previous HAllocate and all | 8854 // TODO(mstarzinger): For now we remove the previous HAllocateObject and |
| 8928 // corresponding instructions and instead add HPushArgument for the | 8855 // add HPushArgument for the arguments in case inlining failed. What we |
| 8929 // arguments in case inlining failed. What we actually should do is for | 8856 // actually should do is emit HInvokeFunction on the constructor instead |
| 8930 // inlining to try to build a subgraph without mutating the parent graph. | 8857 // of using HCallNew as a fallback. |
| 8931 HInstruction* instr = current_block()->last(); | |
| 8932 while (instr != initial_map_value) { | |
| 8933 HInstruction* prev_instr = instr->previous(); | |
| 8934 instr->DeleteAndReplaceWith(NULL); | |
| 8935 instr = prev_instr; | |
| 8936 } | |
| 8937 initial_map_value->DeleteAndReplaceWith(NULL); | |
| 8938 receiver->DeleteAndReplaceWith(NULL); | 8858 receiver->DeleteAndReplaceWith(NULL); |
| 8939 check->DeleteAndReplaceWith(NULL); | 8859 check->DeleteAndReplaceWith(NULL); |
| 8940 environment()->SetExpressionStackAt(receiver_index, function); | 8860 environment()->SetExpressionStackAt(receiver_index, function); |
| 8941 HInstruction* call = PreProcessCall( | 8861 HInstruction* call = PreProcessCall( |
| 8942 new(zone()) HCallNew(context, function, argument_count)); | 8862 new(zone()) HCallNew(context, function, argument_count)); |
| 8943 call->set_position(expr->position()); | 8863 call->set_position(expr->position()); |
| 8944 return ast_context()->ReturnInstruction(call, expr->id()); | 8864 return ast_context()->ReturnInstruction(call, expr->id()); |
| 8945 } else { | 8865 } else { |
| 8946 // The constructor function is both an operand to the instruction and an | 8866 // The constructor function is both an operand to the instruction and an |
| 8947 // argument to the construct call. | 8867 // argument to the construct call. |
| 8948 Handle<JSFunction> array_function = | 8868 Handle<JSFunction> array_function( |
| 8949 Handle<JSFunction>(isolate()->global_context()->array_function(), | 8869 isolate()->global_context()->array_function(), isolate()); |
| 8950 isolate()); | |
| 8951 bool use_call_new_array = FLAG_optimize_constructed_arrays && | |
| 8952 expr->target().is_identical_to(array_function); | |
| 8953 | |
| 8954 CHECK_ALIVE(VisitArgument(expr->expression())); | 8870 CHECK_ALIVE(VisitArgument(expr->expression())); |
| 8955 HValue* constructor = HPushArgument::cast(Top())->argument(); | 8871 HValue* constructor = HPushArgument::cast(Top())->argument(); |
| 8956 CHECK_ALIVE(VisitArgumentList(expr->arguments())); | 8872 CHECK_ALIVE(VisitArgumentList(expr->arguments())); |
| 8957 HCallNew* call; | 8873 HCallNew* call; |
| 8958 if (use_call_new_array) { | 8874 if (expr->target().is_identical_to(array_function)) { |
| 8959 Handle<Cell> cell = expr->allocation_info_cell(); | 8875 Handle<Cell> cell = expr->allocation_info_cell(); |
| 8960 AddInstruction(new(zone()) HCheckFunction(constructor, array_function)); | 8876 AddInstruction(new(zone()) HCheckFunction(constructor, array_function)); |
| 8961 call = new(zone()) HCallNewArray(context, constructor, argument_count, | 8877 call = new(zone()) HCallNewArray(context, constructor, argument_count, |
| 8962 cell); | 8878 cell); |
| 8963 } else { | 8879 } else { |
| 8964 call = new(zone()) HCallNew(context, constructor, argument_count); | 8880 call = new(zone()) HCallNew(context, constructor, argument_count); |
| 8965 } | 8881 } |
| 8966 Drop(argument_count); | 8882 Drop(argument_count); |
| 8967 call->set_position(expr->position()); | 8883 call->set_position(expr->position()); |
| 8968 return ast_context()->ReturnInstruction(call, expr->id()); | 8884 return ast_context()->ReturnInstruction(call, expr->id()); |
| (...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9089 return ast_context()->ReturnInstruction(instr, expr->id()); | 9005 return ast_context()->ReturnInstruction(instr, expr->id()); |
| 9090 } | 9006 } |
| 9091 | 9007 |
| 9092 | 9008 |
| 9093 void HOptimizedGraphBuilder::VisitSub(UnaryOperation* expr) { | 9009 void HOptimizedGraphBuilder::VisitSub(UnaryOperation* expr) { |
| 9094 CHECK_ALIVE(VisitForValue(expr->expression())); | 9010 CHECK_ALIVE(VisitForValue(expr->expression())); |
| 9095 HValue* value = Pop(); | 9011 HValue* value = Pop(); |
| 9096 HValue* context = environment()->LookupContext(); | 9012 HValue* context = environment()->LookupContext(); |
| 9097 HInstruction* instr = | 9013 HInstruction* instr = |
| 9098 HMul::New(zone(), context, value, graph()->GetConstantMinus1()); | 9014 HMul::New(zone(), context, value, graph()->GetConstantMinus1()); |
| 9099 Handle<Type> type = expr->type(); | 9015 Handle<Type> operand_type = expr->expression()->lower_type(); |
| 9100 Representation rep = ToRepresentation(type); | 9016 Representation rep = ToRepresentation(operand_type); |
| 9101 if (type->Is(Type::None())) { | 9017 if (operand_type->Is(Type::None())) { |
| 9102 AddSoftDeoptimize(); | 9018 AddSoftDeoptimize(); |
| 9103 type = handle(Type::Any(), isolate()); | |
| 9104 } | 9019 } |
| 9105 if (instr->IsBinaryOperation()) { | 9020 if (instr->IsBinaryOperation()) { |
| 9106 HBinaryOperation::cast(instr)->set_observed_input_representation(1, rep); | 9021 HBinaryOperation::cast(instr)->set_observed_input_representation(1, rep); |
| 9107 HBinaryOperation::cast(instr)->set_observed_input_representation(2, rep); | 9022 HBinaryOperation::cast(instr)->set_observed_input_representation(2, rep); |
| 9108 } | 9023 } |
| 9109 return ast_context()->ReturnInstruction(instr, expr->id()); | 9024 return ast_context()->ReturnInstruction(instr, expr->id()); |
| 9110 } | 9025 } |
| 9111 | 9026 |
| 9112 | 9027 |
| 9113 void HOptimizedGraphBuilder::VisitBitNot(UnaryOperation* expr) { | 9028 void HOptimizedGraphBuilder::VisitBitNot(UnaryOperation* expr) { |
| 9114 CHECK_ALIVE(VisitForValue(expr->expression())); | 9029 CHECK_ALIVE(VisitForValue(expr->expression())); |
| 9115 HValue* value = Pop(); | 9030 HValue* value = Pop(); |
| 9116 Handle<Type> info = expr->type(); | 9031 Handle<Type> operand_type = expr->expression()->lower_type(); |
| 9117 if (info->Is(Type::None())) { | 9032 if (operand_type->Is(Type::None())) { |
| 9118 AddSoftDeoptimize(); | 9033 AddSoftDeoptimize(); |
| 9119 } | 9034 } |
| 9120 HInstruction* instr = new(zone()) HBitNot(value); | 9035 HInstruction* instr = new(zone()) HBitNot(value); |
| 9121 return ast_context()->ReturnInstruction(instr, expr->id()); | 9036 return ast_context()->ReturnInstruction(instr, expr->id()); |
| 9122 } | 9037 } |
| 9123 | 9038 |
| 9124 | 9039 |
| 9125 void HOptimizedGraphBuilder::VisitNot(UnaryOperation* expr) { | 9040 void HOptimizedGraphBuilder::VisitNot(UnaryOperation* expr) { |
| 9126 if (ast_context()->IsTest()) { | 9041 if (ast_context()->IsTest()) { |
| 9127 TestContext* context = TestContext::cast(ast_context()); | 9042 TestContext* context = TestContext::cast(ast_context()); |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9165 if (join != NULL) return ast_context()->ReturnValue(Pop()); | 9080 if (join != NULL) return ast_context()->ReturnValue(Pop()); |
| 9166 } | 9081 } |
| 9167 | 9082 |
| 9168 | 9083 |
| 9169 HInstruction* HOptimizedGraphBuilder::BuildIncrement( | 9084 HInstruction* HOptimizedGraphBuilder::BuildIncrement( |
| 9170 bool returns_original_input, | 9085 bool returns_original_input, |
| 9171 CountOperation* expr) { | 9086 CountOperation* expr) { |
| 9172 // The input to the count operation is on top of the expression stack. | 9087 // The input to the count operation is on top of the expression stack. |
| 9173 TypeInfo info = expr->type(); | 9088 TypeInfo info = expr->type(); |
| 9174 Representation rep = ToRepresentation(info); | 9089 Representation rep = ToRepresentation(info); |
| 9175 if (rep.IsTagged()) { | 9090 if (rep.IsNone() || rep.IsTagged()) { |
| 9176 rep = Representation::Integer32(); | 9091 rep = Representation::Smi(); |
| 9177 } | 9092 } |
| 9178 | 9093 |
| 9179 if (returns_original_input) { | 9094 if (returns_original_input) { |
| 9180 // We need an explicit HValue representing ToNumber(input). The | 9095 // We need an explicit HValue representing ToNumber(input). The |
| 9181 // actual HChange instruction we need is (sometimes) added in a later | 9096 // actual HChange instruction we need is (sometimes) added in a later |
| 9182 // phase, so it is not available now to be used as an input to HAdd and | 9097 // phase, so it is not available now to be used as an input to HAdd and |
| 9183 // as the return value. | 9098 // as the return value. |
| 9184 HInstruction* number_input = new(zone()) HForceRepresentation(Pop(), rep); | 9099 HInstruction* number_input = new(zone()) HForceRepresentation(Pop(), rep); |
| 9100 if (!rep.IsDouble()) { |
| 9101 number_input->SetFlag(HInstruction::kFlexibleRepresentation); |
| 9102 number_input->SetFlag(HInstruction::kCannotBeTagged); |
| 9103 } |
| 9185 AddInstruction(number_input); | 9104 AddInstruction(number_input); |
| 9186 Push(number_input); | 9105 Push(number_input); |
| 9187 } | 9106 } |
| 9188 | 9107 |
| 9189 // The addition has no side effects, so we do not need | 9108 // The addition has no side effects, so we do not need |
| 9190 // to simulate the expression stack after this instruction. | 9109 // to simulate the expression stack after this instruction. |
| 9191 // Any later failures deopt to the load of the input or earlier. | 9110 // Any later failures deopt to the load of the input or earlier. |
| 9192 HConstant* delta = (expr->op() == Token::INC) | 9111 HConstant* delta = (expr->op() == Token::INC) |
| 9193 ? graph()->GetConstant1() | 9112 ? graph()->GetConstant1() |
| 9194 : graph()->GetConstantMinus1(); | 9113 : graph()->GetConstantMinus1(); |
| 9195 HValue* context = environment()->LookupContext(); | 9114 HValue* context = environment()->LookupContext(); |
| 9196 HInstruction* instr = HAdd::New(zone(), context, Top(), delta); | 9115 HInstruction* instr = HAdd::New(zone(), context, Top(), delta); |
| 9197 // We can't insert a simulate here, because it would break deoptimization, | 9116 instr->SetFlag(HInstruction::kCannotBeTagged); |
| 9198 // so the HAdd must not have side effects, so we must freeze its | |
| 9199 // representation. | |
| 9200 instr->AssumeRepresentation(rep); | |
| 9201 instr->ClearAllSideEffects(); | 9117 instr->ClearAllSideEffects(); |
| 9202 AddInstruction(instr); | 9118 AddInstruction(instr); |
| 9203 return instr; | 9119 return instr; |
| 9204 } | 9120 } |
| 9205 | 9121 |
| 9206 | 9122 |
| 9207 void HOptimizedGraphBuilder::VisitCountOperation(CountOperation* expr) { | 9123 void HOptimizedGraphBuilder::VisitCountOperation(CountOperation* expr) { |
| 9208 ASSERT(!HasStackOverflow()); | 9124 ASSERT(!HasStackOverflow()); |
| 9209 ASSERT(current_block() != NULL); | 9125 ASSERT(current_block() != NULL); |
| 9210 ASSERT(current_block()->HasPredecessor()); | 9126 ASSERT(current_block()->HasPredecessor()); |
| (...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9398 HConstant* c_index = HConstant::cast(index); | 9314 HConstant* c_index = HConstant::cast(index); |
| 9399 if (c_string->HasStringValue() && c_index->HasNumberValue()) { | 9315 if (c_string->HasStringValue() && c_index->HasNumberValue()) { |
| 9400 int32_t i = c_index->NumberValueAsInteger32(); | 9316 int32_t i = c_index->NumberValueAsInteger32(); |
| 9401 Handle<String> s = c_string->StringValue(); | 9317 Handle<String> s = c_string->StringValue(); |
| 9402 if (i < 0 || i >= s->length()) { | 9318 if (i < 0 || i >= s->length()) { |
| 9403 return new(zone()) HConstant(OS::nan_value()); | 9319 return new(zone()) HConstant(OS::nan_value()); |
| 9404 } | 9320 } |
| 9405 return new(zone()) HConstant(s->Get(i)); | 9321 return new(zone()) HConstant(s->Get(i)); |
| 9406 } | 9322 } |
| 9407 } | 9323 } |
| 9408 BuildCheckNonSmi(string); | 9324 BuildCheckHeapObject(string); |
| 9409 AddInstruction(HCheckInstanceType::NewIsString(string, zone())); | 9325 AddInstruction(HCheckInstanceType::NewIsString(string, zone())); |
| 9410 HInstruction* length = HStringLength::New(zone(), string); | 9326 HInstruction* length = HStringLength::New(zone(), string); |
| 9411 AddInstruction(length); | 9327 AddInstruction(length); |
| 9412 HInstruction* checked_index = AddBoundsCheck(index, length); | 9328 HInstruction* checked_index = AddBoundsCheck(index, length); |
| 9413 return new(zone()) HStringCharCodeAt(context, string, checked_index); | 9329 return new(zone()) HStringCharCodeAt(context, string, checked_index); |
| 9414 } | 9330 } |
| 9415 | 9331 |
| 9416 // Checks if the given shift amounts have form: (sa) and (32 - sa). | 9332 // Checks if the given shift amounts have form: (sa) and (32 - sa). |
| 9417 static bool ShiftAmountsAllowReplaceByRotate(HValue* sa, | 9333 static bool ShiftAmountsAllowReplaceByRotate(HValue* sa, |
| 9418 HValue* const32_minus_sa) { | 9334 HValue* const32_minus_sa) { |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9469 } | 9385 } |
| 9470 return true; | 9386 return true; |
| 9471 } | 9387 } |
| 9472 | 9388 |
| 9473 | 9389 |
| 9474 HInstruction* HOptimizedGraphBuilder::BuildBinaryOperation( | 9390 HInstruction* HOptimizedGraphBuilder::BuildBinaryOperation( |
| 9475 BinaryOperation* expr, | 9391 BinaryOperation* expr, |
| 9476 HValue* left, | 9392 HValue* left, |
| 9477 HValue* right) { | 9393 HValue* right) { |
| 9478 HValue* context = environment()->LookupContext(); | 9394 HValue* context = environment()->LookupContext(); |
| 9479 Handle<Type> left_type = expr->left_type(); | 9395 Handle<Type> left_type = expr->left()->lower_type(); |
| 9480 Handle<Type> right_type = expr->right_type(); | 9396 Handle<Type> right_type = expr->right()->lower_type(); |
| 9481 Handle<Type> result_type = expr->result_type(); | 9397 Handle<Type> result_type = expr->lower_type(); |
| 9482 bool has_fixed_right_arg = expr->has_fixed_right_arg(); | 9398 Maybe<int> fixed_right_arg = expr->fixed_right_arg(); |
| 9483 int fixed_right_arg_value = expr->fixed_right_arg_value(); | |
| 9484 Representation left_rep = ToRepresentation(left_type); | 9399 Representation left_rep = ToRepresentation(left_type); |
| 9485 Representation right_rep = ToRepresentation(right_type); | 9400 Representation right_rep = ToRepresentation(right_type); |
| 9486 Representation result_rep = ToRepresentation(result_type); | 9401 Representation result_rep = ToRepresentation(result_type); |
| 9487 if (left_type->Is(Type::None())) { | 9402 if (left_type->Is(Type::None())) { |
| 9488 AddSoftDeoptimize(); | 9403 AddSoftDeoptimize(); |
| 9404 // TODO(rossberg): we should be able to get rid of non-continuous defaults. |
| 9489 left_type = handle(Type::Any(), isolate()); | 9405 left_type = handle(Type::Any(), isolate()); |
| 9490 } | 9406 } |
| 9491 if (right_type->Is(Type::None())) { | 9407 if (right_type->Is(Type::None())) { |
| 9492 AddSoftDeoptimize(); | 9408 AddSoftDeoptimize(); |
| 9493 right_type = handle(Type::Any(), isolate()); | 9409 right_type = handle(Type::Any(), isolate()); |
| 9494 } | 9410 } |
| 9495 HInstruction* instr = NULL; | 9411 HInstruction* instr = NULL; |
| 9496 switch (expr->op()) { | 9412 switch (expr->op()) { |
| 9497 case Token::ADD: | 9413 case Token::ADD: |
| 9498 if (left_type->Is(Type::String()) && right_type->Is(Type::String())) { | 9414 if (left_type->Is(Type::String()) && right_type->Is(Type::String())) { |
| 9499 BuildCheckNonSmi(left); | 9415 BuildCheckHeapObject(left); |
| 9500 AddInstruction(HCheckInstanceType::NewIsString(left, zone())); | 9416 AddInstruction(HCheckInstanceType::NewIsString(left, zone())); |
| 9501 BuildCheckNonSmi(right); | 9417 BuildCheckHeapObject(right); |
| 9502 AddInstruction(HCheckInstanceType::NewIsString(right, zone())); | 9418 AddInstruction(HCheckInstanceType::NewIsString(right, zone())); |
| 9503 instr = HStringAdd::New(zone(), context, left, right); | 9419 instr = HStringAdd::New(zone(), context, left, right); |
| 9504 } else { | 9420 } else { |
| 9505 instr = HAdd::New(zone(), context, left, right); | 9421 instr = HAdd::New(zone(), context, left, right); |
| 9506 } | 9422 } |
| 9507 break; | 9423 break; |
| 9508 case Token::SUB: | 9424 case Token::SUB: |
| 9509 instr = HSub::New(zone(), context, left, right); | 9425 instr = HSub::New(zone(), context, left, right); |
| 9510 break; | 9426 break; |
| 9511 case Token::MUL: | 9427 case Token::MUL: |
| 9512 instr = HMul::New(zone(), context, left, right); | 9428 instr = HMul::New(zone(), context, left, right); |
| 9513 break; | 9429 break; |
| 9514 case Token::MOD: | 9430 case Token::MOD: |
| 9515 instr = HMod::New(zone(), | 9431 instr = HMod::New(zone(), context, left, right, fixed_right_arg); |
| 9516 context, | |
| 9517 left, | |
| 9518 right, | |
| 9519 has_fixed_right_arg, | |
| 9520 fixed_right_arg_value); | |
| 9521 break; | 9432 break; |
| 9522 case Token::DIV: | 9433 case Token::DIV: |
| 9523 instr = HDiv::New(zone(), context, left, right); | 9434 instr = HDiv::New(zone(), context, left, right); |
| 9524 break; | 9435 break; |
| 9525 case Token::BIT_XOR: | 9436 case Token::BIT_XOR: |
| 9526 case Token::BIT_AND: | 9437 case Token::BIT_AND: |
| 9527 instr = HBitwise::New(zone(), expr->op(), context, left, right); | 9438 instr = HBitwise::New(zone(), expr->op(), context, left, right); |
| 9528 break; | 9439 break; |
| 9529 case Token::BIT_OR: { | 9440 case Token::BIT_OR: { |
| 9530 HValue* operand, *shift_amount; | 9441 HValue* operand, *shift_amount; |
| 9531 if (left_type->Is(Type::Integer32()) && | 9442 if (left_type->Is(Type::Signed32()) && |
| 9532 right_type->Is(Type::Integer32()) && | 9443 right_type->Is(Type::Signed32()) && |
| 9533 MatchRotateRight(left, right, &operand, &shift_amount)) { | 9444 MatchRotateRight(left, right, &operand, &shift_amount)) { |
| 9534 instr = new(zone()) HRor(context, operand, shift_amount); | 9445 instr = new(zone()) HRor(context, operand, shift_amount); |
| 9535 } else { | 9446 } else { |
| 9536 instr = HBitwise::New(zone(), expr->op(), context, left, right); | 9447 instr = HBitwise::New(zone(), expr->op(), context, left, right); |
| 9537 } | 9448 } |
| 9538 break; | 9449 break; |
| 9539 } | 9450 } |
| 9540 case Token::SAR: | 9451 case Token::SAR: |
| 9541 instr = HSar::New(zone(), context, left, right); | 9452 instr = HSar::New(zone(), context, left, right); |
| 9542 break; | 9453 break; |
| (...skipping 21 matching lines...) Expand all Loading... |
| 9564 } | 9475 } |
| 9565 | 9476 |
| 9566 | 9477 |
| 9567 // Check for the form (%_ClassOf(foo) === 'BarClass'). | 9478 // Check for the form (%_ClassOf(foo) === 'BarClass'). |
| 9568 static bool IsClassOfTest(CompareOperation* expr) { | 9479 static bool IsClassOfTest(CompareOperation* expr) { |
| 9569 if (expr->op() != Token::EQ_STRICT) return false; | 9480 if (expr->op() != Token::EQ_STRICT) return false; |
| 9570 CallRuntime* call = expr->left()->AsCallRuntime(); | 9481 CallRuntime* call = expr->left()->AsCallRuntime(); |
| 9571 if (call == NULL) return false; | 9482 if (call == NULL) return false; |
| 9572 Literal* literal = expr->right()->AsLiteral(); | 9483 Literal* literal = expr->right()->AsLiteral(); |
| 9573 if (literal == NULL) return false; | 9484 if (literal == NULL) return false; |
| 9574 if (!literal->handle()->IsString()) return false; | 9485 if (!literal->value()->IsString()) return false; |
| 9575 if (!call->name()->IsOneByteEqualTo(STATIC_ASCII_VECTOR("_ClassOf"))) { | 9486 if (!call->name()->IsOneByteEqualTo(STATIC_ASCII_VECTOR("_ClassOf"))) { |
| 9576 return false; | 9487 return false; |
| 9577 } | 9488 } |
| 9578 ASSERT(call->arguments()->length() == 1); | 9489 ASSERT(call->arguments()->length() == 1); |
| 9579 return true; | 9490 return true; |
| 9580 } | 9491 } |
| 9581 | 9492 |
| 9582 | 9493 |
| 9583 void HOptimizedGraphBuilder::VisitBinaryOperation(BinaryOperation* expr) { | 9494 void HOptimizedGraphBuilder::VisitBinaryOperation(BinaryOperation* expr) { |
| 9584 ASSERT(!HasStackOverflow()); | 9495 ASSERT(!HasStackOverflow()); |
| (...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9722 if (info.IsSmi()) return Representation::Integer32(); | 9633 if (info.IsSmi()) return Representation::Integer32(); |
| 9723 if (info.IsInteger32()) return Representation::Integer32(); | 9634 if (info.IsInteger32()) return Representation::Integer32(); |
| 9724 if (info.IsDouble()) return Representation::Double(); | 9635 if (info.IsDouble()) return Representation::Double(); |
| 9725 if (info.IsNumber()) return Representation::Double(); | 9636 if (info.IsNumber()) return Representation::Double(); |
| 9726 return Representation::Tagged(); | 9637 return Representation::Tagged(); |
| 9727 } | 9638 } |
| 9728 | 9639 |
| 9729 | 9640 |
| 9730 Representation HOptimizedGraphBuilder::ToRepresentation(Handle<Type> type) { | 9641 Representation HOptimizedGraphBuilder::ToRepresentation(Handle<Type> type) { |
| 9731 if (type->Is(Type::None())) return Representation::None(); | 9642 if (type->Is(Type::None())) return Representation::None(); |
| 9732 if (type->Is(Type::Integer32())) return Representation::Integer32(); | 9643 if (type->Is(Type::Signed32())) return Representation::Integer32(); |
| 9733 if (type->Is(Type::Number())) return Representation::Double(); | 9644 if (type->Is(Type::Number())) return Representation::Double(); |
| 9734 return Representation::Tagged(); | 9645 return Representation::Tagged(); |
| 9735 } | 9646 } |
| 9736 | 9647 |
| 9737 | 9648 |
| 9738 void HOptimizedGraphBuilder::HandleLiteralCompareTypeof(CompareOperation* expr, | 9649 void HOptimizedGraphBuilder::HandleLiteralCompareTypeof(CompareOperation* expr, |
| 9739 HTypeof* typeof_expr, | 9650 HTypeof* typeof_expr, |
| 9740 Handle<String> check) { | 9651 Handle<String> check) { |
| 9741 // Note: The HTypeof itself is removed during canonicalization, if possible. | 9652 // Note: The HTypeof itself is removed during canonicalization, if possible. |
| 9742 HValue* value = typeof_expr->value(); | 9653 HValue* value = typeof_expr->value(); |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9810 void HOptimizedGraphBuilder::VisitCompareOperation(CompareOperation* expr) { | 9721 void HOptimizedGraphBuilder::VisitCompareOperation(CompareOperation* expr) { |
| 9811 ASSERT(!HasStackOverflow()); | 9722 ASSERT(!HasStackOverflow()); |
| 9812 ASSERT(current_block() != NULL); | 9723 ASSERT(current_block() != NULL); |
| 9813 ASSERT(current_block()->HasPredecessor()); | 9724 ASSERT(current_block()->HasPredecessor()); |
| 9814 if (IsClassOfTest(expr)) { | 9725 if (IsClassOfTest(expr)) { |
| 9815 CallRuntime* call = expr->left()->AsCallRuntime(); | 9726 CallRuntime* call = expr->left()->AsCallRuntime(); |
| 9816 ASSERT(call->arguments()->length() == 1); | 9727 ASSERT(call->arguments()->length() == 1); |
| 9817 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 9728 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
| 9818 HValue* value = Pop(); | 9729 HValue* value = Pop(); |
| 9819 Literal* literal = expr->right()->AsLiteral(); | 9730 Literal* literal = expr->right()->AsLiteral(); |
| 9820 Handle<String> rhs = Handle<String>::cast(literal->handle()); | 9731 Handle<String> rhs = Handle<String>::cast(literal->value()); |
| 9821 HClassOfTestAndBranch* instr = | 9732 HClassOfTestAndBranch* instr = |
| 9822 new(zone()) HClassOfTestAndBranch(value, rhs); | 9733 new(zone()) HClassOfTestAndBranch(value, rhs); |
| 9823 instr->set_position(expr->position()); | 9734 instr->set_position(expr->position()); |
| 9824 return ast_context()->ReturnControl(instr, expr->id()); | 9735 return ast_context()->ReturnControl(instr, expr->id()); |
| 9825 } | 9736 } |
| 9826 | 9737 |
| 9827 Handle<Type> left_type = expr->left_type(); | 9738 Handle<Type> left_type = expr->left()->lower_type(); |
| 9828 Handle<Type> right_type = expr->right_type(); | 9739 Handle<Type> right_type = expr->right()->lower_type(); |
| 9829 Handle<Type> overall_type = expr->overall_type(); | 9740 Handle<Type> combined_type = expr->combined_type(); |
| 9830 Representation combined_rep = ToRepresentation(overall_type); | 9741 Representation combined_rep = ToRepresentation(combined_type); |
| 9831 Representation left_rep = ToRepresentation(left_type); | 9742 Representation left_rep = ToRepresentation(left_type); |
| 9832 Representation right_rep = ToRepresentation(right_type); | 9743 Representation right_rep = ToRepresentation(right_type); |
| 9833 // Check if this expression was ever executed according to type feedback. | 9744 // Check if this expression was ever executed according to type feedback. |
| 9834 // Note that for the special typeof/null/undefined cases we get unknown here. | 9745 // Note that for the special typeof/null/undefined cases we get unknown here. |
| 9835 if (overall_type->Is(Type::None())) { | 9746 if (combined_type->Is(Type::None())) { |
| 9836 AddSoftDeoptimize(); | 9747 AddSoftDeoptimize(); |
| 9837 overall_type = left_type = right_type = handle(Type::Any(), isolate()); | 9748 combined_type = left_type = right_type = handle(Type::Any(), isolate()); |
| 9838 } | 9749 } |
| 9839 | 9750 |
| 9840 CHECK_ALIVE(VisitForValue(expr->left())); | 9751 CHECK_ALIVE(VisitForValue(expr->left())); |
| 9841 CHECK_ALIVE(VisitForValue(expr->right())); | 9752 CHECK_ALIVE(VisitForValue(expr->right())); |
| 9842 | 9753 |
| 9843 HValue* context = environment()->LookupContext(); | 9754 HValue* context = environment()->LookupContext(); |
| 9844 HValue* right = Pop(); | 9755 HValue* right = Pop(); |
| 9845 HValue* left = Pop(); | 9756 HValue* left = Pop(); |
| 9846 Token::Value op = expr->op(); | 9757 Token::Value op = expr->op(); |
| 9847 | 9758 |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9899 AddInstruction(new(zone()) HCheckFunction(right, target)); | 9810 AddInstruction(new(zone()) HCheckFunction(right, target)); |
| 9900 HInstanceOfKnownGlobal* result = | 9811 HInstanceOfKnownGlobal* result = |
| 9901 new(zone()) HInstanceOfKnownGlobal(context, left, target); | 9812 new(zone()) HInstanceOfKnownGlobal(context, left, target); |
| 9902 result->set_position(expr->position()); | 9813 result->set_position(expr->position()); |
| 9903 return ast_context()->ReturnInstruction(result, expr->id()); | 9814 return ast_context()->ReturnInstruction(result, expr->id()); |
| 9904 } | 9815 } |
| 9905 } else if (op == Token::IN) { | 9816 } else if (op == Token::IN) { |
| 9906 HIn* result = new(zone()) HIn(context, left, right); | 9817 HIn* result = new(zone()) HIn(context, left, right); |
| 9907 result->set_position(expr->position()); | 9818 result->set_position(expr->position()); |
| 9908 return ast_context()->ReturnInstruction(result, expr->id()); | 9819 return ast_context()->ReturnInstruction(result, expr->id()); |
| 9909 } else if (overall_type->Is(Type::Receiver())) { | 9820 } else if (combined_type->Is(Type::Receiver())) { |
| 9910 switch (op) { | 9821 switch (op) { |
| 9911 case Token::EQ: | 9822 case Token::EQ: |
| 9912 case Token::EQ_STRICT: { | 9823 case Token::EQ_STRICT: { |
| 9913 // Can we get away with map check and not instance type check? | 9824 // Can we get away with map check and not instance type check? |
| 9914 if (overall_type->IsClass()) { | 9825 if (combined_type->IsClass()) { |
| 9915 Handle<Map> map = overall_type->AsClass(); | 9826 Handle<Map> map = combined_type->AsClass(); |
| 9916 AddCheckMapsWithTransitions(left, map); | 9827 AddCheckMapsWithTransitions(left, map); |
| 9917 AddCheckMapsWithTransitions(right, map); | 9828 AddCheckMapsWithTransitions(right, map); |
| 9918 HCompareObjectEqAndBranch* result = | 9829 HCompareObjectEqAndBranch* result = |
| 9919 new(zone()) HCompareObjectEqAndBranch(left, right); | 9830 new(zone()) HCompareObjectEqAndBranch(left, right); |
| 9920 result->set_position(expr->position()); | 9831 result->set_position(expr->position()); |
| 9921 return ast_context()->ReturnControl(result, expr->id()); | 9832 return ast_context()->ReturnControl(result, expr->id()); |
| 9922 } else { | 9833 } else { |
| 9923 BuildCheckNonSmi(left); | 9834 BuildCheckHeapObject(left); |
| 9924 AddInstruction(HCheckInstanceType::NewIsSpecObject(left, zone())); | 9835 AddInstruction(HCheckInstanceType::NewIsSpecObject(left, zone())); |
| 9925 BuildCheckNonSmi(right); | 9836 BuildCheckHeapObject(right); |
| 9926 AddInstruction(HCheckInstanceType::NewIsSpecObject(right, zone())); | 9837 AddInstruction(HCheckInstanceType::NewIsSpecObject(right, zone())); |
| 9927 HCompareObjectEqAndBranch* result = | 9838 HCompareObjectEqAndBranch* result = |
| 9928 new(zone()) HCompareObjectEqAndBranch(left, right); | 9839 new(zone()) HCompareObjectEqAndBranch(left, right); |
| 9929 result->set_position(expr->position()); | 9840 result->set_position(expr->position()); |
| 9930 return ast_context()->ReturnControl(result, expr->id()); | 9841 return ast_context()->ReturnControl(result, expr->id()); |
| 9931 } | 9842 } |
| 9932 } | 9843 } |
| 9933 default: | 9844 default: |
| 9934 return Bailout("Unsupported non-primitive compare"); | 9845 return Bailout("Unsupported non-primitive compare"); |
| 9935 } | 9846 } |
| 9936 } else if (overall_type->Is(Type::InternalizedString()) && | 9847 } else if (combined_type->Is(Type::InternalizedString()) && |
| 9937 Token::IsEqualityOp(op)) { | 9848 Token::IsEqualityOp(op)) { |
| 9938 BuildCheckNonSmi(left); | 9849 BuildCheckHeapObject(left); |
| 9939 AddInstruction(HCheckInstanceType::NewIsInternalizedString(left, zone())); | 9850 AddInstruction(HCheckInstanceType::NewIsInternalizedString(left, zone())); |
| 9940 BuildCheckNonSmi(right); | 9851 BuildCheckHeapObject(right); |
| 9941 AddInstruction(HCheckInstanceType::NewIsInternalizedString(right, zone())); | 9852 AddInstruction(HCheckInstanceType::NewIsInternalizedString(right, zone())); |
| 9942 HCompareObjectEqAndBranch* result = | 9853 HCompareObjectEqAndBranch* result = |
| 9943 new(zone()) HCompareObjectEqAndBranch(left, right); | 9854 new(zone()) HCompareObjectEqAndBranch(left, right); |
| 9944 result->set_position(expr->position()); | 9855 result->set_position(expr->position()); |
| 9945 return ast_context()->ReturnControl(result, expr->id()); | 9856 return ast_context()->ReturnControl(result, expr->id()); |
| 9946 } else { | 9857 } else { |
| 9947 if (combined_rep.IsTagged() || combined_rep.IsNone()) { | 9858 if (combined_rep.IsTagged() || combined_rep.IsNone()) { |
| 9948 HCompareGeneric* result = | 9859 HCompareGeneric* result = |
| 9949 new(zone()) HCompareGeneric(context, left, right, op); | 9860 new(zone()) HCompareGeneric(context, left, right, op); |
| 9950 result->set_observed_input_representation(1, left_rep); | 9861 result->set_observed_input_representation(1, left_rep); |
| 9951 result->set_observed_input_representation(2, right_rep); | 9862 result->set_observed_input_representation(2, right_rep); |
| 9952 result->set_position(expr->position()); | 9863 result->set_position(expr->position()); |
| 9953 return ast_context()->ReturnInstruction(result, expr->id()); | 9864 return ast_context()->ReturnInstruction(result, expr->id()); |
| 9954 } else { | 9865 } else { |
| 9955 // TODO(verwaest): Remove once ToRepresentation properly returns Smi when | 9866 // TODO(verwaest): Remove once ToRepresentation properly returns Smi when |
| 9956 // the IC measures Smi. | 9867 // the IC measures Smi. |
| 9957 if (left_type->Is(Type::Integer31())) left_rep = Representation::Smi(); | 9868 if (left_type->Is(Type::Smi())) left_rep = Representation::Smi(); |
| 9958 if (right_type->Is(Type::Integer31())) right_rep = Representation::Smi(); | 9869 if (right_type->Is(Type::Smi())) right_rep = Representation::Smi(); |
| 9959 HCompareIDAndBranch* result = | 9870 HCompareIDAndBranch* result = |
| 9960 new(zone()) HCompareIDAndBranch(left, right, op); | 9871 new(zone()) HCompareIDAndBranch(left, right, op); |
| 9961 result->set_observed_input_representation(left_rep, right_rep); | 9872 result->set_observed_input_representation(left_rep, right_rep); |
| 9962 result->set_position(expr->position()); | 9873 result->set_position(expr->position()); |
| 9963 return ast_context()->ReturnControl(result, expr->id()); | 9874 return ast_context()->ReturnControl(result, expr->id()); |
| 9964 } | 9875 } |
| 9965 } | 9876 } |
| 9966 } | 9877 } |
| 9967 | 9878 |
| 9968 | 9879 |
| 9969 void HOptimizedGraphBuilder::HandleLiteralCompareNil(CompareOperation* expr, | 9880 void HOptimizedGraphBuilder::HandleLiteralCompareNil(CompareOperation* expr, |
| 9970 HValue* value, | 9881 HValue* value, |
| 9971 NilValue nil) { | 9882 NilValue nil) { |
| 9972 ASSERT(!HasStackOverflow()); | 9883 ASSERT(!HasStackOverflow()); |
| 9973 ASSERT(current_block() != NULL); | 9884 ASSERT(current_block() != NULL); |
| 9974 ASSERT(current_block()->HasPredecessor()); | 9885 ASSERT(current_block()->HasPredecessor()); |
| 9975 ASSERT(expr->op() == Token::EQ || expr->op() == Token::EQ_STRICT); | 9886 ASSERT(expr->op() == Token::EQ || expr->op() == Token::EQ_STRICT); |
| 9976 HIfContinuation continuation; | 9887 HIfContinuation continuation; |
| 9977 if (expr->op() == Token::EQ_STRICT) { | 9888 if (expr->op() == Token::EQ_STRICT) { |
| 9978 IfBuilder if_nil(this); | 9889 IfBuilder if_nil(this); |
| 9979 if_nil.If<HCompareObjectEqAndBranch>( | 9890 if_nil.If<HCompareObjectEqAndBranch>( |
| 9980 value, (nil == kNullValue) ? graph()->GetConstantNull() | 9891 value, (nil == kNullValue) ? graph()->GetConstantNull() |
| 9981 : graph()->GetConstantUndefined()); | 9892 : graph()->GetConstantUndefined()); |
| 9982 if_nil.Then(); | 9893 if_nil.Then(); |
| 9983 if_nil.Else(); | 9894 if_nil.Else(); |
| 9984 if_nil.CaptureContinuation(&continuation); | 9895 if_nil.CaptureContinuation(&continuation); |
| 9985 return ast_context()->ReturnContinuation(&continuation, expr->id()); | 9896 return ast_context()->ReturnContinuation(&continuation, expr->id()); |
| 9986 } | 9897 } |
| 9987 Handle<Type> type = expr->compare_nil_type()->Is(Type::None()) | 9898 Handle<Type> type = expr->combined_type()->Is(Type::None()) |
| 9988 ? handle(Type::Any(), isolate_) : expr->compare_nil_type(); | 9899 ? handle(Type::Any(), isolate_) : expr->combined_type(); |
| 9989 BuildCompareNil(value, type, expr->position(), &continuation); | 9900 BuildCompareNil(value, type, expr->position(), &continuation); |
| 9990 return ast_context()->ReturnContinuation(&continuation, expr->id()); | 9901 return ast_context()->ReturnContinuation(&continuation, expr->id()); |
| 9991 } | 9902 } |
| 9992 | 9903 |
| 9993 | 9904 |
| 9994 HInstruction* HOptimizedGraphBuilder::BuildThisFunction() { | 9905 HInstruction* HOptimizedGraphBuilder::BuildThisFunction() { |
| 9995 // If we share optimized code between different closures, the | 9906 // If we share optimized code between different closures, the |
| 9996 // this-function is not a constant, except inside an inlined body. | 9907 // this-function is not a constant, except inside an inlined body. |
| 9997 if (function_state()->outer() != NULL) { | 9908 if (function_state()->outer() != NULL) { |
| 9998 return new(zone()) HConstant( | 9909 return new(zone()) HConstant( |
| 9999 function_state()->compilation_info()->closure()); | 9910 function_state()->compilation_info()->closure()); |
| 10000 } else { | 9911 } else { |
| 10001 return new(zone()) HThisFunction; | 9912 return new(zone()) HThisFunction; |
| 10002 } | 9913 } |
| 10003 } | 9914 } |
| 10004 | 9915 |
| 10005 | 9916 |
| 10006 HInstruction* HOptimizedGraphBuilder::BuildFastLiteral( | 9917 HInstruction* HOptimizedGraphBuilder::BuildFastLiteral( |
| 10007 HValue* context, | 9918 HValue* context, |
| 10008 Handle<JSObject> boilerplate_object, | 9919 Handle<JSObject> boilerplate_object, |
| 10009 Handle<JSObject> original_boilerplate_object, | 9920 Handle<JSObject> original_boilerplate_object, |
| 10010 int data_size, | 9921 int data_size, |
| 10011 int pointer_size, | 9922 int pointer_size, |
| 10012 AllocationSiteMode mode) { | 9923 AllocationSiteMode mode) { |
| 10013 Zone* zone = this->zone(); | 9924 Zone* zone = this->zone(); |
| 10014 int total_size = data_size + pointer_size; | |
| 10015 | |
| 10016 NoObservableSideEffectsScope no_effects(this); | 9925 NoObservableSideEffectsScope no_effects(this); |
| 10017 | 9926 |
| 10018 HAllocate::Flags flags = HAllocate::CAN_ALLOCATE_IN_NEW_SPACE; | 9927 HInstruction* target = NULL; |
| 10019 // TODO(hpayer): add support for old data space | 9928 HInstruction* data_target = NULL; |
| 10020 if (isolate()->heap()->ShouldGloballyPretenure() && | 9929 |
| 10021 data_size == 0) { | 9930 HAllocate::Flags flags = HAllocate::DefaultFlags(); |
| 10022 flags = static_cast<HAllocate::Flags>( | 9931 |
| 10023 flags | HAllocate::CAN_ALLOCATE_IN_OLD_POINTER_SPACE); | 9932 if (isolate()->heap()->ShouldGloballyPretenure()) { |
| 9933 if (data_size != 0) { |
| 9934 HAllocate::Flags data_flags = |
| 9935 static_cast<HAllocate::Flags>(HAllocate::DefaultFlags() | |
| 9936 HAllocate::CAN_ALLOCATE_IN_OLD_DATA_SPACE); |
| 9937 HValue* size_in_bytes = AddInstruction(new(zone) HConstant(data_size)); |
| 9938 data_target = AddInstruction(new(zone) HAllocate( |
| 9939 context, size_in_bytes, HType::JSObject(), data_flags)); |
| 9940 Handle<Map> free_space_map = isolate()->factory()->free_space_map(); |
| 9941 AddStoreMapConstant(data_target, free_space_map); |
| 9942 HObjectAccess access = |
| 9943 HObjectAccess::ForJSObjectOffset(FreeSpace::kSizeOffset); |
| 9944 AddStore(data_target, access, size_in_bytes); |
| 9945 } |
| 9946 if (pointer_size != 0) { |
| 9947 flags = static_cast<HAllocate::Flags>( |
| 9948 flags | HAllocate::CAN_ALLOCATE_IN_OLD_POINTER_SPACE); |
| 9949 HValue* size_in_bytes = AddInstruction(new(zone) HConstant(pointer_size)); |
| 9950 target = AddInstruction(new(zone) HAllocate(context, |
| 9951 size_in_bytes, HType::JSObject(), flags)); |
| 9952 } |
| 9953 } else { |
| 9954 HValue* size_in_bytes = |
| 9955 AddInstruction(new(zone) HConstant(data_size + pointer_size)); |
| 9956 target = AddInstruction(new(zone) HAllocate(context, size_in_bytes, |
| 9957 HType::JSObject(), flags)); |
| 10024 } | 9958 } |
| 10025 | 9959 |
| 10026 HValue* size_in_bytes = AddInstruction(new(zone) HConstant(total_size)); | |
| 10027 HInstruction* result = | |
| 10028 AddInstruction(new(zone) HAllocate(context, | |
| 10029 size_in_bytes, | |
| 10030 HType::JSObject(), | |
| 10031 flags)); | |
| 10032 int offset = 0; | 9960 int offset = 0; |
| 10033 BuildEmitDeepCopy(boilerplate_object, original_boilerplate_object, result, | 9961 int data_offset = 0; |
| 10034 &offset, mode); | 9962 BuildEmitDeepCopy(boilerplate_object, original_boilerplate_object, target, |
| 10035 return result; | 9963 &offset, data_target, &data_offset, mode); |
| 9964 return target; |
| 10036 } | 9965 } |
| 10037 | 9966 |
| 10038 | 9967 |
| 10039 void HOptimizedGraphBuilder::BuildEmitDeepCopy( | 9968 void HOptimizedGraphBuilder::BuildEmitDeepCopy( |
| 10040 Handle<JSObject> boilerplate_object, | 9969 Handle<JSObject> boilerplate_object, |
| 10041 Handle<JSObject> original_boilerplate_object, | 9970 Handle<JSObject> original_boilerplate_object, |
| 10042 HInstruction* target, | 9971 HInstruction* target, |
| 10043 int* offset, | 9972 int* offset, |
| 9973 HInstruction* data_target, |
| 9974 int* data_offset, |
| 10044 AllocationSiteMode mode) { | 9975 AllocationSiteMode mode) { |
| 10045 Zone* zone = this->zone(); | 9976 Zone* zone = this->zone(); |
| 10046 | 9977 |
| 10047 Handle<FixedArrayBase> elements(boilerplate_object->elements()); | 9978 Handle<FixedArrayBase> elements(boilerplate_object->elements()); |
| 10048 Handle<FixedArrayBase> original_elements( | 9979 Handle<FixedArrayBase> original_elements( |
| 10049 original_boilerplate_object->elements()); | 9980 original_boilerplate_object->elements()); |
| 10050 ElementsKind kind = boilerplate_object->map()->elements_kind(); | 9981 ElementsKind kind = boilerplate_object->map()->elements_kind(); |
| 10051 | 9982 |
| 10052 // Increase the offset so that subsequent objects end up right after | |
| 10053 // this object and its backing store. | |
| 10054 int object_offset = *offset; | 9983 int object_offset = *offset; |
| 10055 int object_size = boilerplate_object->map()->instance_size(); | 9984 int object_size = boilerplate_object->map()->instance_size(); |
| 10056 int elements_size = (elements->length() > 0 && | 9985 int elements_size = (elements->length() > 0 && |
| 10057 elements->map() != isolate()->heap()->fixed_cow_array_map()) ? | 9986 elements->map() != isolate()->heap()->fixed_cow_array_map()) ? |
| 10058 elements->Size() : 0; | 9987 elements->Size() : 0; |
| 10059 int elements_offset = *offset + object_size; | 9988 int elements_offset = 0; |
| 10060 | 9989 |
| 10061 *offset += object_size + elements_size; | 9990 if (data_target != NULL && boilerplate_object->HasFastDoubleElements()) { |
| 9991 elements_offset = *data_offset; |
| 9992 *data_offset += elements_size; |
| 9993 } else { |
| 9994 // Place elements right after this object. |
| 9995 elements_offset = *offset + object_size; |
| 9996 *offset += elements_size; |
| 9997 } |
| 9998 // Increase the offset so that subsequent objects end up right after this |
| 9999 // object (and it's elements if they are allocated in the same space). |
| 10000 *offset += object_size; |
| 10062 | 10001 |
| 10063 // Copy object elements if non-COW. | 10002 // Copy object elements if non-COW. |
| 10064 HValue* object_elements = BuildEmitObjectHeader(boilerplate_object, target, | 10003 HValue* object_elements = BuildEmitObjectHeader(boilerplate_object, target, |
| 10065 object_offset, elements_offset, elements_size); | 10004 data_target, object_offset, elements_offset, elements_size); |
| 10066 if (object_elements != NULL) { | 10005 if (object_elements != NULL) { |
| 10067 BuildEmitElements(elements, original_elements, kind, object_elements, | 10006 BuildEmitElements(elements, original_elements, kind, object_elements, |
| 10068 target, offset); | 10007 target, offset, data_target, data_offset); |
| 10069 } | 10008 } |
| 10070 | 10009 |
| 10071 // Copy in-object properties. | 10010 // Copy in-object properties. |
| 10072 HValue* object_properties = | 10011 HValue* object_properties = |
| 10073 AddInstruction(new(zone) HInnerAllocatedObject(target, object_offset)); | 10012 AddInstruction(new(zone) HInnerAllocatedObject(target, object_offset)); |
| 10074 BuildEmitInObjectProperties(boilerplate_object, original_boilerplate_object, | 10013 BuildEmitInObjectProperties(boilerplate_object, original_boilerplate_object, |
| 10075 object_properties, target, offset); | 10014 object_properties, target, offset, data_target, data_offset); |
| 10076 | 10015 |
| 10077 // Create allocation site info. | 10016 // Create allocation site info. |
| 10078 if (mode == TRACK_ALLOCATION_SITE && | 10017 if (mode == TRACK_ALLOCATION_SITE && |
| 10079 boilerplate_object->map()->CanTrackAllocationSite()) { | 10018 boilerplate_object->map()->CanTrackAllocationSite()) { |
| 10080 elements_offset += AllocationSiteInfo::kSize; | 10019 elements_offset += AllocationSiteInfo::kSize; |
| 10081 *offset += AllocationSiteInfo::kSize; | 10020 *offset += AllocationSiteInfo::kSize; |
| 10082 HInstruction* original_boilerplate = AddInstruction(new(zone) HConstant( | 10021 HInstruction* original_boilerplate = AddInstruction(new(zone) HConstant( |
| 10083 original_boilerplate_object)); | 10022 original_boilerplate_object)); |
| 10084 BuildCreateAllocationSiteInfo(target, JSArray::kSize, original_boilerplate); | 10023 BuildCreateAllocationSiteInfo(target, JSArray::kSize, original_boilerplate); |
| 10085 } | 10024 } |
| 10086 } | 10025 } |
| 10087 | 10026 |
| 10088 | 10027 |
| 10089 HValue* HOptimizedGraphBuilder::BuildEmitObjectHeader( | 10028 HValue* HOptimizedGraphBuilder::BuildEmitObjectHeader( |
| 10090 Handle<JSObject> boilerplate_object, | 10029 Handle<JSObject> boilerplate_object, |
| 10091 HInstruction* target, | 10030 HInstruction* target, |
| 10031 HInstruction* data_target, |
| 10092 int object_offset, | 10032 int object_offset, |
| 10093 int elements_offset, | 10033 int elements_offset, |
| 10094 int elements_size) { | 10034 int elements_size) { |
| 10095 ASSERT(boilerplate_object->properties()->length() == 0); | 10035 ASSERT(boilerplate_object->properties()->length() == 0); |
| 10096 Zone* zone = this->zone(); | 10036 Zone* zone = this->zone(); |
| 10097 HValue* result = NULL; | 10037 HValue* result = NULL; |
| 10098 | 10038 |
| 10099 HValue* object_header = | 10039 HValue* object_header = |
| 10100 AddInstruction(new(zone) HInnerAllocatedObject(target, object_offset)); | 10040 AddInstruction(new(zone) HInnerAllocatedObject(target, object_offset)); |
| 10101 Handle<Map> boilerplate_object_map(boilerplate_object->map()); | 10041 Handle<Map> boilerplate_object_map(boilerplate_object->map()); |
| 10102 AddStoreMapConstant(object_header, boilerplate_object_map); | 10042 AddStoreMapConstant(object_header, boilerplate_object_map); |
| 10103 | 10043 |
| 10104 HInstruction* elements; | 10044 HInstruction* elements; |
| 10105 if (elements_size == 0) { | 10045 if (elements_size == 0) { |
| 10106 Handle<Object> elements_field = | 10046 Handle<Object> elements_field = |
| 10107 Handle<Object>(boilerplate_object->elements(), isolate()); | 10047 Handle<Object>(boilerplate_object->elements(), isolate()); |
| 10108 elements = AddInstruction(new(zone) HConstant(elements_field)); | 10048 elements = AddInstruction(new(zone) HConstant(elements_field)); |
| 10109 } else { | 10049 } else { |
| 10110 elements = AddInstruction(new(zone) HInnerAllocatedObject( | 10050 if (data_target != NULL && boilerplate_object->HasFastDoubleElements()) { |
| 10111 target, elements_offset)); | 10051 elements = AddInstruction(new(zone) HInnerAllocatedObject( |
| 10052 data_target, elements_offset)); |
| 10053 } else { |
| 10054 elements = AddInstruction(new(zone) HInnerAllocatedObject( |
| 10055 target, elements_offset)); |
| 10056 } |
| 10112 result = elements; | 10057 result = elements; |
| 10113 } | 10058 } |
| 10114 AddStore(object_header, HObjectAccess::ForElementsPointer(), elements); | 10059 AddStore(object_header, HObjectAccess::ForElementsPointer(), elements); |
| 10115 | 10060 |
| 10116 Handle<Object> properties_field = | 10061 Handle<Object> properties_field = |
| 10117 Handle<Object>(boilerplate_object->properties(), isolate()); | 10062 Handle<Object>(boilerplate_object->properties(), isolate()); |
| 10118 ASSERT(*properties_field == isolate()->heap()->empty_fixed_array()); | 10063 ASSERT(*properties_field == isolate()->heap()->empty_fixed_array()); |
| 10119 HInstruction* properties = AddInstruction(new(zone) HConstant( | 10064 HInstruction* properties = AddInstruction(new(zone) HConstant( |
| 10120 properties_field)); | 10065 properties_field)); |
| 10121 HObjectAccess access = HObjectAccess::ForPropertiesPointer(); | 10066 HObjectAccess access = HObjectAccess::ForPropertiesPointer(); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 10138 | 10083 |
| 10139 return result; | 10084 return result; |
| 10140 } | 10085 } |
| 10141 | 10086 |
| 10142 | 10087 |
| 10143 void HOptimizedGraphBuilder::BuildEmitInObjectProperties( | 10088 void HOptimizedGraphBuilder::BuildEmitInObjectProperties( |
| 10144 Handle<JSObject> boilerplate_object, | 10089 Handle<JSObject> boilerplate_object, |
| 10145 Handle<JSObject> original_boilerplate_object, | 10090 Handle<JSObject> original_boilerplate_object, |
| 10146 HValue* object_properties, | 10091 HValue* object_properties, |
| 10147 HInstruction* target, | 10092 HInstruction* target, |
| 10148 int* offset) { | 10093 int* offset, |
| 10094 HInstruction* data_target, |
| 10095 int* data_offset) { |
| 10149 Zone* zone = this->zone(); | 10096 Zone* zone = this->zone(); |
| 10150 Handle<DescriptorArray> descriptors( | 10097 Handle<DescriptorArray> descriptors( |
| 10151 boilerplate_object->map()->instance_descriptors()); | 10098 boilerplate_object->map()->instance_descriptors()); |
| 10152 int limit = boilerplate_object->map()->NumberOfOwnDescriptors(); | 10099 int limit = boilerplate_object->map()->NumberOfOwnDescriptors(); |
| 10153 | 10100 |
| 10154 int copied_fields = 0; | 10101 int copied_fields = 0; |
| 10155 for (int i = 0; i < limit; i++) { | 10102 for (int i = 0; i < limit; i++) { |
| 10156 PropertyDetails details = descriptors->GetDetails(i); | 10103 PropertyDetails details = descriptors->GetDetails(i); |
| 10157 if (details.type() != FIELD) continue; | 10104 if (details.type() != FIELD) continue; |
| 10158 copied_fields++; | 10105 copied_fields++; |
| (...skipping 13 matching lines...) Expand all Loading... |
| 10172 Handle<JSObject> value_object = Handle<JSObject>::cast(value); | 10119 Handle<JSObject> value_object = Handle<JSObject>::cast(value); |
| 10173 Handle<JSObject> original_value_object = Handle<JSObject>::cast( | 10120 Handle<JSObject> original_value_object = Handle<JSObject>::cast( |
| 10174 Handle<Object>(original_boilerplate_object->InObjectPropertyAt(index), | 10121 Handle<Object>(original_boilerplate_object->InObjectPropertyAt(index), |
| 10175 isolate())); | 10122 isolate())); |
| 10176 HInstruction* value_instruction = | 10123 HInstruction* value_instruction = |
| 10177 AddInstruction(new(zone) HInnerAllocatedObject(target, *offset)); | 10124 AddInstruction(new(zone) HInnerAllocatedObject(target, *offset)); |
| 10178 | 10125 |
| 10179 AddStore(object_properties, access, value_instruction); | 10126 AddStore(object_properties, access, value_instruction); |
| 10180 | 10127 |
| 10181 BuildEmitDeepCopy(value_object, original_value_object, target, | 10128 BuildEmitDeepCopy(value_object, original_value_object, target, |
| 10182 offset, DONT_TRACK_ALLOCATION_SITE); | 10129 offset, data_target, data_offset, DONT_TRACK_ALLOCATION_SITE); |
| 10183 } else { | 10130 } else { |
| 10184 Representation representation = details.representation(); | 10131 Representation representation = details.representation(); |
| 10185 HInstruction* value_instruction = | 10132 HInstruction* value_instruction = |
| 10186 AddInstruction(new(zone) HConstant(value)); | 10133 AddInstruction(new(zone) HConstant(value)); |
| 10187 | 10134 |
| 10188 if (representation.IsDouble()) { | 10135 if (representation.IsDouble()) { |
| 10189 // Allocate a HeapNumber box and store the value into it. | 10136 // Allocate a HeapNumber box and store the value into it. |
| 10190 HInstruction* double_box = | 10137 HInstruction* double_box; |
| 10191 AddInstruction(new(zone) HInnerAllocatedObject(target, *offset)); | 10138 if (data_target != NULL) { |
| 10139 double_box = AddInstruction(new(zone) HInnerAllocatedObject( |
| 10140 data_target, *data_offset)); |
| 10141 *data_offset += HeapNumber::kSize; |
| 10142 } else { |
| 10143 double_box = AddInstruction(new(zone) HInnerAllocatedObject( |
| 10144 target, *offset)); |
| 10145 *offset += HeapNumber::kSize; |
| 10146 } |
| 10192 AddStoreMapConstant(double_box, | 10147 AddStoreMapConstant(double_box, |
| 10193 isolate()->factory()->heap_number_map()); | 10148 isolate()->factory()->heap_number_map()); |
| 10194 AddStore(double_box, HObjectAccess::ForHeapNumberValue(), | 10149 AddStore(double_box, HObjectAccess::ForHeapNumberValue(), |
| 10195 value_instruction, Representation::Double()); | 10150 value_instruction, Representation::Double()); |
| 10196 value_instruction = double_box; | 10151 value_instruction = double_box; |
| 10197 *offset += HeapNumber::kSize; | |
| 10198 } | 10152 } |
| 10199 | 10153 |
| 10200 AddStore(object_properties, access, value_instruction); | 10154 AddStore(object_properties, access, value_instruction); |
| 10201 } | 10155 } |
| 10202 } | 10156 } |
| 10203 | 10157 |
| 10204 int inobject_properties = boilerplate_object->map()->inobject_properties(); | 10158 int inobject_properties = boilerplate_object->map()->inobject_properties(); |
| 10205 HInstruction* value_instruction = AddInstruction(new(zone) | 10159 HInstruction* value_instruction = AddInstruction(new(zone) |
| 10206 HConstant(isolate()->factory()->one_pointer_filler_map())); | 10160 HConstant(isolate()->factory()->one_pointer_filler_map())); |
| 10207 for (int i = copied_fields; i < inobject_properties; i++) { | 10161 for (int i = copied_fields; i < inobject_properties; i++) { |
| 10208 ASSERT(boilerplate_object->IsJSObject()); | 10162 ASSERT(boilerplate_object->IsJSObject()); |
| 10209 int property_offset = boilerplate_object->GetInObjectPropertyOffset(i); | 10163 int property_offset = boilerplate_object->GetInObjectPropertyOffset(i); |
| 10210 HObjectAccess access = HObjectAccess::ForJSObjectOffset(property_offset); | 10164 HObjectAccess access = HObjectAccess::ForJSObjectOffset(property_offset); |
| 10211 AddStore(object_properties, access, value_instruction); | 10165 AddStore(object_properties, access, value_instruction); |
| 10212 } | 10166 } |
| 10213 } | 10167 } |
| 10214 | 10168 |
| 10215 | 10169 |
| 10216 void HOptimizedGraphBuilder::BuildEmitElements( | 10170 void HOptimizedGraphBuilder::BuildEmitElements( |
| 10217 Handle<FixedArrayBase> elements, | 10171 Handle<FixedArrayBase> elements, |
| 10218 Handle<FixedArrayBase> original_elements, | 10172 Handle<FixedArrayBase> original_elements, |
| 10219 ElementsKind kind, | 10173 ElementsKind kind, |
| 10220 HValue* object_elements, | 10174 HValue* object_elements, |
| 10221 HInstruction* target, | 10175 HInstruction* target, |
| 10222 int* offset) { | 10176 int* offset, |
| 10177 HInstruction* data_target, |
| 10178 int* data_offset) { |
| 10223 Zone* zone = this->zone(); | 10179 Zone* zone = this->zone(); |
| 10224 | 10180 |
| 10225 int elements_length = elements->length(); | 10181 int elements_length = elements->length(); |
| 10226 HValue* object_elements_length = | 10182 HValue* object_elements_length = |
| 10227 AddInstruction(new(zone) HConstant(elements_length)); | 10183 AddInstruction(new(zone) HConstant(elements_length)); |
| 10228 | 10184 |
| 10229 BuildInitializeElementsHeader(object_elements, kind, object_elements_length); | 10185 BuildInitializeElementsHeader(object_elements, kind, object_elements_length); |
| 10230 | 10186 |
| 10231 // Copy elements backing store content. | 10187 // Copy elements backing store content. |
| 10232 if (elements->IsFixedDoubleArray()) { | 10188 if (elements->IsFixedDoubleArray()) { |
| 10233 BuildEmitFixedDoubleArray(elements, kind, object_elements); | 10189 BuildEmitFixedDoubleArray(elements, kind, object_elements); |
| 10234 } else if (elements->IsFixedArray()) { | 10190 } else if (elements->IsFixedArray()) { |
| 10235 BuildEmitFixedArray(elements, original_elements, kind, object_elements, | 10191 BuildEmitFixedArray(elements, original_elements, kind, object_elements, |
| 10236 target, offset); | 10192 target, offset, data_target, data_offset); |
| 10237 } else { | 10193 } else { |
| 10238 UNREACHABLE(); | 10194 UNREACHABLE(); |
| 10239 } | 10195 } |
| 10240 } | 10196 } |
| 10241 | 10197 |
| 10242 | 10198 |
| 10243 void HOptimizedGraphBuilder::BuildEmitFixedDoubleArray( | 10199 void HOptimizedGraphBuilder::BuildEmitFixedDoubleArray( |
| 10244 Handle<FixedArrayBase> elements, | 10200 Handle<FixedArrayBase> elements, |
| 10245 ElementsKind kind, | 10201 ElementsKind kind, |
| 10246 HValue* object_elements) { | 10202 HValue* object_elements) { |
| (...skipping 12 matching lines...) Expand all Loading... |
| 10259 } | 10215 } |
| 10260 } | 10216 } |
| 10261 | 10217 |
| 10262 | 10218 |
| 10263 void HOptimizedGraphBuilder::BuildEmitFixedArray( | 10219 void HOptimizedGraphBuilder::BuildEmitFixedArray( |
| 10264 Handle<FixedArrayBase> elements, | 10220 Handle<FixedArrayBase> elements, |
| 10265 Handle<FixedArrayBase> original_elements, | 10221 Handle<FixedArrayBase> original_elements, |
| 10266 ElementsKind kind, | 10222 ElementsKind kind, |
| 10267 HValue* object_elements, | 10223 HValue* object_elements, |
| 10268 HInstruction* target, | 10224 HInstruction* target, |
| 10269 int* offset) { | 10225 int* offset, |
| 10226 HInstruction* data_target, |
| 10227 int* data_offset) { |
| 10270 Zone* zone = this->zone(); | 10228 Zone* zone = this->zone(); |
| 10271 HInstruction* boilerplate_elements = | 10229 HInstruction* boilerplate_elements = |
| 10272 AddInstruction(new(zone) HConstant(elements)); | 10230 AddInstruction(new(zone) HConstant(elements)); |
| 10273 int elements_length = elements->length(); | 10231 int elements_length = elements->length(); |
| 10274 Handle<FixedArray> fast_elements = Handle<FixedArray>::cast(elements); | 10232 Handle<FixedArray> fast_elements = Handle<FixedArray>::cast(elements); |
| 10275 Handle<FixedArray> original_fast_elements = | 10233 Handle<FixedArray> original_fast_elements = |
| 10276 Handle<FixedArray>::cast(original_elements); | 10234 Handle<FixedArray>::cast(original_elements); |
| 10277 for (int i = 0; i < elements_length; i++) { | 10235 for (int i = 0; i < elements_length; i++) { |
| 10278 Handle<Object> value(fast_elements->get(i), isolate()); | 10236 Handle<Object> value(fast_elements->get(i), isolate()); |
| 10279 HValue* key_constant = AddInstruction(new(zone) HConstant(i)); | 10237 HValue* key_constant = AddInstruction(new(zone) HConstant(i)); |
| 10280 if (value->IsJSObject()) { | 10238 if (value->IsJSObject()) { |
| 10281 Handle<JSObject> value_object = Handle<JSObject>::cast(value); | 10239 Handle<JSObject> value_object = Handle<JSObject>::cast(value); |
| 10282 Handle<JSObject> original_value_object = Handle<JSObject>::cast( | 10240 Handle<JSObject> original_value_object = Handle<JSObject>::cast( |
| 10283 Handle<Object>(original_fast_elements->get(i), isolate())); | 10241 Handle<Object>(original_fast_elements->get(i), isolate())); |
| 10284 HInstruction* value_instruction = | 10242 HInstruction* value_instruction = |
| 10285 AddInstruction(new(zone) HInnerAllocatedObject(target, *offset)); | 10243 AddInstruction(new(zone) HInnerAllocatedObject(target, *offset)); |
| 10286 AddInstruction(new(zone) HStoreKeyed( | 10244 AddInstruction(new(zone) HStoreKeyed( |
| 10287 object_elements, key_constant, value_instruction, kind)); | 10245 object_elements, key_constant, value_instruction, kind)); |
| 10288 BuildEmitDeepCopy(value_object, original_value_object, target, | 10246 BuildEmitDeepCopy(value_object, original_value_object, target, |
| 10289 offset, DONT_TRACK_ALLOCATION_SITE); | 10247 offset, data_target, data_offset, DONT_TRACK_ALLOCATION_SITE); |
| 10290 } else { | 10248 } else { |
| 10291 HInstruction* value_instruction = | 10249 HInstruction* value_instruction = |
| 10292 AddInstruction(new(zone) HLoadKeyed( | 10250 AddInstruction(new(zone) HLoadKeyed( |
| 10293 boilerplate_elements, key_constant, NULL, kind, | 10251 boilerplate_elements, key_constant, NULL, kind, |
| 10294 ALLOW_RETURN_HOLE)); | 10252 ALLOW_RETURN_HOLE)); |
| 10295 AddInstruction(new(zone) HStoreKeyed( | 10253 AddInstruction(new(zone) HStoreKeyed( |
| 10296 object_elements, key_constant, value_instruction, kind)); | 10254 object_elements, key_constant, value_instruction, kind)); |
| 10297 } | 10255 } |
| 10298 } | 10256 } |
| 10299 } | 10257 } |
| (...skipping 301 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10601 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 10559 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
| 10602 HValue* value = Pop(); | 10560 HValue* value = Pop(); |
| 10603 HValueOf* result = new(zone()) HValueOf(value); | 10561 HValueOf* result = new(zone()) HValueOf(value); |
| 10604 return ast_context()->ReturnInstruction(result, call->id()); | 10562 return ast_context()->ReturnInstruction(result, call->id()); |
| 10605 } | 10563 } |
| 10606 | 10564 |
| 10607 | 10565 |
| 10608 void HOptimizedGraphBuilder::GenerateDateField(CallRuntime* call) { | 10566 void HOptimizedGraphBuilder::GenerateDateField(CallRuntime* call) { |
| 10609 ASSERT(call->arguments()->length() == 2); | 10567 ASSERT(call->arguments()->length() == 2); |
| 10610 ASSERT_NE(NULL, call->arguments()->at(1)->AsLiteral()); | 10568 ASSERT_NE(NULL, call->arguments()->at(1)->AsLiteral()); |
| 10611 Smi* index = Smi::cast(*(call->arguments()->at(1)->AsLiteral()->handle())); | 10569 Smi* index = Smi::cast(*(call->arguments()->at(1)->AsLiteral()->value())); |
| 10612 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 10570 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
| 10613 HValue* date = Pop(); | 10571 HValue* date = Pop(); |
| 10614 HDateField* result = new(zone()) HDateField(date, index); | 10572 HDateField* result = new(zone()) HDateField(date, index); |
| 10615 return ast_context()->ReturnInstruction(result, call->id()); | 10573 return ast_context()->ReturnInstruction(result, call->id()); |
| 10616 } | 10574 } |
| 10617 | 10575 |
| 10618 | 10576 |
| 10619 void HOptimizedGraphBuilder::GenerateOneByteSeqStringSetChar( | 10577 void HOptimizedGraphBuilder::GenerateOneByteSeqStringSetChar( |
| 10620 CallRuntime* call) { | 10578 CallRuntime* call) { |
| 10621 ASSERT(call->arguments()->length() == 3); | 10579 ASSERT(call->arguments()->length() == 3); |
| (...skipping 889 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 11511 | 11469 |
| 11512 | 11470 |
| 11513 void HStatistics::Print() { | 11471 void HStatistics::Print() { |
| 11514 PrintF("Timing results:\n"); | 11472 PrintF("Timing results:\n"); |
| 11515 int64_t sum = 0; | 11473 int64_t sum = 0; |
| 11516 for (int i = 0; i < timing_.length(); ++i) { | 11474 for (int i = 0; i < timing_.length(); ++i) { |
| 11517 sum += timing_[i]; | 11475 sum += timing_[i]; |
| 11518 } | 11476 } |
| 11519 | 11477 |
| 11520 for (int i = 0; i < names_.length(); ++i) { | 11478 for (int i = 0; i < names_.length(); ++i) { |
| 11521 PrintF("%30s", names_[i]); | 11479 PrintF("%32s", names_[i]); |
| 11522 double ms = static_cast<double>(timing_[i]) / 1000; | 11480 double ms = static_cast<double>(timing_[i]) / 1000; |
| 11523 double percent = static_cast<double>(timing_[i]) * 100 / sum; | 11481 double percent = static_cast<double>(timing_[i]) * 100 / sum; |
| 11524 PrintF(" - %8.3f ms / %4.1f %% ", ms, percent); | 11482 PrintF(" %8.3f ms / %4.1f %% ", ms, percent); |
| 11525 | 11483 |
| 11526 unsigned size = sizes_[i]; | 11484 unsigned size = sizes_[i]; |
| 11527 double size_percent = static_cast<double>(size) * 100 / total_size_; | 11485 double size_percent = static_cast<double>(size) * 100 / total_size_; |
| 11528 PrintF(" %9u bytes / %4.1f %%\n", size, size_percent); | 11486 PrintF(" %9u bytes / %4.1f %%\n", size, size_percent); |
| 11529 } | 11487 } |
| 11530 | 11488 |
| 11531 PrintF("----------------------------------------" | 11489 PrintF("----------------------------------------" |
| 11532 "---------------------------------------\n"); | 11490 "---------------------------------------\n"); |
| 11533 int64_t total = create_graph_ + optimize_graph_ + generate_code_; | 11491 int64_t total = create_graph_ + optimize_graph_ + generate_code_; |
| 11534 PrintF("%30s - %8.3f ms / %4.1f %% \n", | 11492 PrintF("%32s %8.3f ms / %4.1f %% \n", |
| 11535 "Create graph", | 11493 "Create graph", |
| 11536 static_cast<double>(create_graph_) / 1000, | 11494 static_cast<double>(create_graph_) / 1000, |
| 11537 static_cast<double>(create_graph_) * 100 / total); | 11495 static_cast<double>(create_graph_) * 100 / total); |
| 11538 PrintF("%30s - %8.3f ms / %4.1f %% \n", | 11496 PrintF("%32s %8.3f ms / %4.1f %% \n", |
| 11539 "Optimize graph", | 11497 "Optimize graph", |
| 11540 static_cast<double>(optimize_graph_) / 1000, | 11498 static_cast<double>(optimize_graph_) / 1000, |
| 11541 static_cast<double>(optimize_graph_) * 100 / total); | 11499 static_cast<double>(optimize_graph_) * 100 / total); |
| 11542 PrintF("%30s - %8.3f ms / %4.1f %% \n", | 11500 PrintF("%32s %8.3f ms / %4.1f %% \n", |
| 11543 "Generate and install code", | 11501 "Generate and install code", |
| 11544 static_cast<double>(generate_code_) / 1000, | 11502 static_cast<double>(generate_code_) / 1000, |
| 11545 static_cast<double>(generate_code_) * 100 / total); | 11503 static_cast<double>(generate_code_) * 100 / total); |
| 11546 PrintF("----------------------------------------" | 11504 PrintF("----------------------------------------" |
| 11547 "---------------------------------------\n"); | 11505 "---------------------------------------\n"); |
| 11548 PrintF("%30s - %8.3f ms (%.1f times slower than full code gen)\n", | 11506 PrintF("%32s %8.3f ms (%.1f times slower than full code gen)\n", |
| 11549 "Total", | 11507 "Total", |
| 11550 static_cast<double>(total) / 1000, | 11508 static_cast<double>(total) / 1000, |
| 11551 static_cast<double>(total) / full_code_gen_); | 11509 static_cast<double>(total) / full_code_gen_); |
| 11552 | 11510 |
| 11553 double source_size_in_kb = static_cast<double>(source_size_) / 1024; | 11511 double source_size_in_kb = static_cast<double>(source_size_) / 1024; |
| 11554 double normalized_time = source_size_in_kb > 0 | 11512 double normalized_time = source_size_in_kb > 0 |
| 11555 ? (static_cast<double>(total) / 1000) / source_size_in_kb | 11513 ? (static_cast<double>(total) / 1000) / source_size_in_kb |
| 11556 : 0; | 11514 : 0; |
| 11557 double normalized_size_in_kb = source_size_in_kb > 0 | 11515 double normalized_size_in_kb = source_size_in_kb > 0 |
| 11558 ? total_size_ / 1024 / source_size_in_kb | 11516 ? total_size_ / 1024 / source_size_in_kb |
| 11559 : 0; | 11517 : 0; |
| 11560 PrintF("%30s - %8.3f ms %7.3f kB allocated\n", | 11518 PrintF("%32s %8.3f ms %7.3f kB allocated\n", |
| 11561 "Average per kB source", | 11519 "Average per kB source", |
| 11562 normalized_time, normalized_size_in_kb); | 11520 normalized_time, normalized_size_in_kb); |
| 11563 } | 11521 } |
| 11564 | 11522 |
| 11565 | 11523 |
| 11566 void HStatistics::SaveTiming(const char* name, int64_t ticks, unsigned size) { | 11524 void HStatistics::SaveTiming(const char* name, int64_t ticks, unsigned size) { |
| 11567 if (name == HPhase::kFullCodeGen) { | 11525 total_size_ += size; |
| 11568 full_code_gen_ += ticks; | 11526 for (int i = 0; i < names_.length(); ++i) { |
| 11569 } else { | 11527 if (strcmp(names_[i], name) == 0) { |
| 11570 total_size_ += size; | 11528 timing_[i] += ticks; |
| 11571 for (int i = 0; i < names_.length(); ++i) { | 11529 sizes_[i] += size; |
| 11572 if (strcmp(names_[i], name) == 0) { | 11530 return; |
| 11573 timing_[i] += ticks; | |
| 11574 sizes_[i] += size; | |
| 11575 return; | |
| 11576 } | |
| 11577 } | 11531 } |
| 11578 names_.Add(name); | |
| 11579 timing_.Add(ticks); | |
| 11580 sizes_.Add(size); | |
| 11581 } | 11532 } |
| 11582 } | 11533 names_.Add(name); |
| 11583 | 11534 timing_.Add(ticks); |
| 11584 | 11535 sizes_.Add(size); |
| 11585 const char* const HPhase::kFullCodeGen = "Full code generator"; | |
| 11586 | |
| 11587 | |
| 11588 HPhase::HPhase(const char* name, Isolate* isolate, Zone* zone) { | |
| 11589 Init(isolate, name, zone, NULL, NULL, NULL); | |
| 11590 } | |
| 11591 | |
| 11592 | |
| 11593 HPhase::HPhase(const char* name, HGraph* graph) { | |
| 11594 Init(graph->isolate(), name, graph->zone(), graph, NULL, NULL); | |
| 11595 } | |
| 11596 | |
| 11597 | |
| 11598 HPhase::HPhase(const char* name, LChunk* chunk) { | |
| 11599 Init(chunk->isolate(), name, chunk->zone(), NULL, chunk, NULL); | |
| 11600 } | |
| 11601 | |
| 11602 | |
| 11603 HPhase::HPhase(const char* name, LAllocator* allocator) { | |
| 11604 Init(allocator->isolate(), name, allocator->zone(), NULL, NULL, allocator); | |
| 11605 } | |
| 11606 | |
| 11607 | |
| 11608 void HPhase::Init(Isolate* isolate, | |
| 11609 const char* name, | |
| 11610 Zone* zone, | |
| 11611 HGraph* graph, | |
| 11612 LChunk* chunk, | |
| 11613 LAllocator* allocator) { | |
| 11614 isolate_ = isolate; | |
| 11615 name_ = name; | |
| 11616 zone_ = zone; | |
| 11617 graph_ = graph; | |
| 11618 chunk_ = chunk; | |
| 11619 allocator_ = allocator; | |
| 11620 if (allocator != NULL && chunk_ == NULL) { | |
| 11621 chunk_ = allocator->chunk(); | |
| 11622 } | |
| 11623 if (FLAG_hydrogen_stats) { | |
| 11624 start_ticks_ = OS::Ticks(); | |
| 11625 start_allocation_size_ = zone_->allocation_size(); | |
| 11626 } | |
| 11627 } | 11536 } |
| 11628 | 11537 |
| 11629 | 11538 |
| 11630 HPhase::~HPhase() { | 11539 HPhase::~HPhase() { |
| 11631 if (FLAG_hydrogen_stats) { | 11540 if (ShouldProduceTraceOutput()) { |
| 11632 int64_t ticks = OS::Ticks() - start_ticks_; | 11541 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); |
| 11633 unsigned size = zone_->allocation_size() - start_allocation_size_; | |
| 11634 isolate_->GetHStatistics()->SaveTiming(name_, ticks, size); | |
| 11635 } | |
| 11636 | |
| 11637 // Produce trace output if flag is set so that the first letter of the | |
| 11638 // phase name matches the command line parameter FLAG_trace_phase. | |
| 11639 if (FLAG_trace_hydrogen && | |
| 11640 OS::StrChr(const_cast<char*>(FLAG_trace_phase), name_[0]) != NULL) { | |
| 11641 if (graph_ != NULL) { | |
| 11642 isolate_->GetHTracer()->TraceHydrogen(name_, graph_); | |
| 11643 } | |
| 11644 if (chunk_ != NULL) { | |
| 11645 isolate_->GetHTracer()->TraceLithium(name_, chunk_); | |
| 11646 } | |
| 11647 if (allocator_ != NULL) { | |
| 11648 isolate_->GetHTracer()->TraceLiveRanges(name_, allocator_); | |
| 11649 } | |
| 11650 } | 11542 } |
| 11651 | 11543 |
| 11652 #ifdef DEBUG | 11544 #ifdef DEBUG |
| 11653 if (graph_ != NULL) graph_->Verify(false); // No full verify. | 11545 graph_->Verify(false); // No full verify. |
| 11654 if (allocator_ != NULL) allocator_->Verify(); | |
| 11655 #endif | 11546 #endif |
| 11656 } | 11547 } |
| 11657 | 11548 |
| 11658 } } // namespace v8::internal | 11549 } } // namespace v8::internal |
| OLD | NEW |