OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 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 4811 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4822 if (count != types->length()) return false; | 4822 if (count != types->length()) return false; |
4823 | 4823 |
4824 // Everything matched; can use monomorphic store. | 4824 // Everything matched; can use monomorphic store. |
4825 BuildCheckHeapObject(object); | 4825 BuildCheckHeapObject(object); |
4826 AddInstruction(HCheckMaps::New(object, types, zone())); | 4826 AddInstruction(HCheckMaps::New(object, types, zone())); |
4827 HInstruction* store; | 4827 HInstruction* store; |
4828 CHECK_ALIVE_OR_RETURN( | 4828 CHECK_ALIVE_OR_RETURN( |
4829 store = BuildStoreNamedField( | 4829 store = BuildStoreNamedField( |
4830 object, name, store_value, types->at(count - 1), &lookup), | 4830 object, name, store_value, types->at(count - 1), &lookup), |
4831 true); | 4831 true); |
4832 if (result_value != NULL) Push(result_value); | 4832 Push(result_value); |
4833 Push(store_value); | |
4834 store->set_position(position); | 4833 store->set_position(position); |
4835 AddInstruction(store); | 4834 AddInstruction(store); |
4836 AddSimulate(assignment_id); | 4835 AddSimulate(assignment_id); |
4837 if (result_value != NULL) Drop(1); | |
4838 ast_context()->ReturnValue(Pop()); | 4836 ast_context()->ReturnValue(Pop()); |
4839 return true; | 4837 return true; |
4840 } | 4838 } |
4841 | 4839 |
4842 | 4840 |
4843 void HOptimizedGraphBuilder::HandlePolymorphicStoreNamedField( | 4841 void HOptimizedGraphBuilder::HandlePolymorphicStoreNamedField( |
4844 BailoutId id, | |
4845 int position, | 4842 int position, |
4846 BailoutId assignment_id, | 4843 BailoutId assignment_id, |
4847 HValue* object, | 4844 HValue* object, |
4848 HValue* store_value, | 4845 HValue* store_value, |
4849 HValue* result_value, | 4846 HValue* result_value, |
4850 SmallMapList* types, | 4847 SmallMapList* types, |
4851 Handle<String> name) { | 4848 Handle<String> name) { |
4852 if (TryStorePolymorphicAsMonomorphic( | 4849 if (TryStorePolymorphicAsMonomorphic( |
4853 position, assignment_id, object, | 4850 position, assignment_id, object, |
4854 store_value, result_value, types, name)) { | 4851 store_value, result_value, types, name)) { |
(...skipping 20 matching lines...) Expand all Loading... |
4875 new(zone()) HCompareMap(object, map, if_true, if_false); | 4872 new(zone()) HCompareMap(object, map, if_true, if_false); |
4876 current_block()->Finish(compare); | 4873 current_block()->Finish(compare); |
4877 | 4874 |
4878 set_current_block(if_true); | 4875 set_current_block(if_true); |
4879 HInstruction* instr; | 4876 HInstruction* instr; |
4880 CHECK_ALIVE(instr = BuildStoreNamedField( | 4877 CHECK_ALIVE(instr = BuildStoreNamedField( |
4881 object, name, store_value, map, &lookup)); | 4878 object, name, store_value, map, &lookup)); |
4882 instr->set_position(position); | 4879 instr->set_position(position); |
4883 // Goto will add the HSimulate for the store. | 4880 // Goto will add the HSimulate for the store. |
4884 AddInstruction(instr); | 4881 AddInstruction(instr); |
4885 if (!ast_context()->IsEffect()) { | 4882 if (!ast_context()->IsEffect()) Push(result_value); |
4886 if (result_value != NULL) Push(result_value); | |
4887 Push(store_value); | |
4888 } | |
4889 current_block()->Goto(join); | 4883 current_block()->Goto(join); |
4890 | 4884 |
4891 set_current_block(if_false); | 4885 set_current_block(if_false); |
4892 } | 4886 } |
4893 } | 4887 } |
4894 | 4888 |
4895 // Finish up. Unconditionally deoptimize if we've handled all the maps we | 4889 // Finish up. Unconditionally deoptimize if we've handled all the maps we |
4896 // know about and do not want to handle ones we've never seen. Otherwise | 4890 // know about and do not want to handle ones we've never seen. Otherwise |
4897 // use a generic IC. | 4891 // use a generic IC. |
4898 if (count == types->length() && FLAG_deoptimize_uncommon_cases) { | 4892 if (count == types->length() && FLAG_deoptimize_uncommon_cases) { |
4899 current_block()->FinishExitWithDeoptimization(HDeoptimize::kNoUses); | 4893 current_block()->FinishExitWithDeoptimization(HDeoptimize::kNoUses); |
4900 } else { | 4894 } else { |
4901 HInstruction* instr = BuildStoreNamedGeneric(object, name, store_value); | 4895 HInstruction* instr = BuildStoreNamedGeneric(object, name, store_value); |
4902 instr->set_position(position); | 4896 instr->set_position(position); |
4903 AddInstruction(instr); | 4897 AddInstruction(instr); |
4904 | 4898 |
4905 if (join != NULL) { | 4899 if (join != NULL) { |
4906 if (!ast_context()->IsEffect()) { | 4900 if (!ast_context()->IsEffect()) { |
4907 if (result_value != NULL) Push(result_value); | 4901 Push(result_value); |
4908 Push(store_value); | |
4909 } | 4902 } |
4910 current_block()->Goto(join); | 4903 current_block()->Goto(join); |
4911 } else { | 4904 } else { |
4912 // The HSimulate for the store should not see the stored value in | 4905 // The HSimulate for the store should not see the stored value in |
4913 // effect contexts (it is not materialized at expr->id() in the | 4906 // effect contexts (it is not materialized at expr->id() in the |
4914 // unoptimized code). | 4907 // unoptimized code). |
4915 if (instr->HasObservableSideEffects()) { | 4908 if (instr->HasObservableSideEffects()) { |
4916 if (ast_context()->IsEffect()) { | 4909 if (ast_context()->IsEffect()) { |
4917 AddSimulate(id, REMOVABLE_SIMULATE); | 4910 AddSimulate(assignment_id, REMOVABLE_SIMULATE); |
4918 } else { | 4911 } else { |
4919 if (result_value != NULL) Push(result_value); | 4912 Push(result_value); |
4920 Push(store_value); | 4913 AddSimulate(assignment_id, REMOVABLE_SIMULATE); |
4921 AddSimulate(id, REMOVABLE_SIMULATE); | 4914 Drop(1); |
4922 Drop(result_value != NULL ? 2 : 1); | |
4923 } | 4915 } |
4924 } | 4916 } |
4925 return ast_context()->ReturnValue( | 4917 return ast_context()->ReturnValue(result_value); |
4926 result_value != NULL ? result_value : store_value); | |
4927 } | 4918 } |
4928 } | 4919 } |
4929 | 4920 |
4930 ASSERT(join != NULL); | 4921 ASSERT(join != NULL); |
4931 join->SetJoinId(id); | 4922 join->SetJoinId(assignment_id); |
4932 set_current_block(join); | 4923 set_current_block(join); |
4933 if (!ast_context()->IsEffect()) { | 4924 if (!ast_context()->IsEffect()) { |
4934 if (result_value != NULL) Drop(1); | |
4935 ast_context()->ReturnValue(Pop()); | 4925 ast_context()->ReturnValue(Pop()); |
4936 } | 4926 } |
4937 } | 4927 } |
4938 | 4928 |
4939 | 4929 |
4940 void HOptimizedGraphBuilder::HandlePropertyAssignment(Assignment* expr) { | 4930 void HOptimizedGraphBuilder::HandlePropertyAssignment(Assignment* expr) { |
4941 Property* prop = expr->target()->AsProperty(); | 4931 Property* prop = expr->target()->AsProperty(); |
4942 ASSERT(prop != NULL); | 4932 ASSERT(prop != NULL); |
4943 CHECK_ALIVE(VisitForValue(prop->obj())); | 4933 CHECK_ALIVE(VisitForValue(prop->obj())); |
4944 | 4934 |
4945 if (prop->key()->IsPropertyName()) { | 4935 if (prop->key()->IsPropertyName()) { |
4946 // Named store. | 4936 // Named store. |
4947 CHECK_ALIVE(VisitForValue(expr->value())); | 4937 CHECK_ALIVE(VisitForValue(expr->value())); |
4948 HValue* value = environment()->ExpressionStackAt(0); | 4938 HValue* value = environment()->ExpressionStackAt(0); |
4949 HValue* object = environment()->ExpressionStackAt(1); | 4939 HValue* object = environment()->ExpressionStackAt(1); |
4950 | 4940 |
4951 if (expr->IsUninitialized()) AddSoftDeoptimize(); | 4941 if (expr->IsUninitialized()) AddSoftDeoptimize(); |
4952 return BuildStoreNamed(expr, expr->id(), expr->position(), | 4942 return BuildStoreNamed(expr, expr->id(), expr->position(), |
4953 expr->AssignmentId(), prop, object, value); | 4943 expr->AssignmentId(), prop, object, value, value); |
4954 } else { | 4944 } else { |
4955 // Keyed store. | 4945 // Keyed store. |
4956 CHECK_ALIVE(VisitForValue(prop->key())); | 4946 CHECK_ALIVE(VisitForValue(prop->key())); |
4957 CHECK_ALIVE(VisitForValue(expr->value())); | 4947 CHECK_ALIVE(VisitForValue(expr->value())); |
4958 HValue* value = environment()->ExpressionStackAt(0); | 4948 HValue* value = environment()->ExpressionStackAt(0); |
4959 HValue* key = environment()->ExpressionStackAt(1); | 4949 HValue* key = environment()->ExpressionStackAt(1); |
4960 HValue* object = environment()->ExpressionStackAt(2); | 4950 HValue* object = environment()->ExpressionStackAt(2); |
4961 bool has_side_effects = false; | 4951 bool has_side_effects = false; |
4962 HandleKeyedElementAccess(object, key, value, expr, expr->AssignmentId(), | 4952 HandleKeyedElementAccess(object, key, value, expr, expr->AssignmentId(), |
4963 expr->position(), | 4953 expr->position(), |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5036 map = types->first(); | 5026 map = types->first(); |
5037 if (map->is_dictionary_map()) monomorphic = false; | 5027 if (map->is_dictionary_map()) monomorphic = false; |
5038 } | 5028 } |
5039 if (monomorphic) { | 5029 if (monomorphic) { |
5040 Handle<JSFunction> setter; | 5030 Handle<JSFunction> setter; |
5041 Handle<JSObject> holder; | 5031 Handle<JSObject> holder; |
5042 if (LookupSetter(map, name, &setter, &holder)) { | 5032 if (LookupSetter(map, name, &setter, &holder)) { |
5043 AddCheckConstantFunction(holder, object, map); | 5033 AddCheckConstantFunction(holder, object, map); |
5044 // Don't try to inline if the result_value is different from the | 5034 // Don't try to inline if the result_value is different from the |
5045 // store_value. That case isn't handled yet by the inlining. | 5035 // store_value. That case isn't handled yet by the inlining. |
5046 if (result_value == NULL && | 5036 if (result_value == store_value && |
5047 FLAG_inline_accessors && | 5037 FLAG_inline_accessors && |
5048 TryInlineSetter(setter, id, assignment_id, store_value)) { | 5038 TryInlineSetter(setter, id, assignment_id, store_value)) { |
5049 return; | 5039 return; |
5050 } | 5040 } |
5051 Drop(2); | 5041 Drop(2); |
5052 Add<HPushArgument>(object); | 5042 Add<HPushArgument>(object); |
5053 Add<HPushArgument>(store_value); | 5043 Add<HPushArgument>(store_value); |
5054 instr = new(zone()) HCallConstantFunction(setter, 2); | 5044 instr = new(zone()) HCallConstantFunction(setter, 2); |
5055 } else { | 5045 } else { |
5056 Drop(2); | 5046 Drop(2); |
5057 CHECK_ALIVE(instr = BuildStoreNamedMonomorphic(object, | 5047 CHECK_ALIVE(instr = BuildStoreNamedMonomorphic(object, |
5058 name, | 5048 name, |
5059 store_value, | 5049 store_value, |
5060 map)); | 5050 map)); |
5061 } | 5051 } |
5062 } else if (types != NULL && types->length() > 1) { | 5052 } else if (types != NULL && types->length() > 1) { |
5063 Drop(2); | 5053 Drop(2); |
5064 return HandlePolymorphicStoreNamedField( | 5054 return HandlePolymorphicStoreNamedField( |
5065 id, position, assignment_id, object, | 5055 position, id, object, |
5066 store_value, result_value, types, name); | 5056 store_value, result_value, types, name); |
5067 } else { | 5057 } else { |
5068 Drop(2); | 5058 Drop(2); |
5069 instr = BuildStoreNamedGeneric(object, name, store_value); | 5059 instr = BuildStoreNamedGeneric(object, name, store_value); |
5070 } | 5060 } |
5071 | 5061 |
5072 if (result_value != NULL) Push(result_value); | 5062 Push(result_value); |
5073 Push(store_value); | |
5074 instr->set_position(position); | 5063 instr->set_position(position); |
5075 AddInstruction(instr); | 5064 AddInstruction(instr); |
5076 if (instr->HasObservableSideEffects()) { | 5065 if (instr->HasObservableSideEffects()) { |
5077 AddSimulate(assignment_id, REMOVABLE_SIMULATE); | 5066 AddSimulate(id, REMOVABLE_SIMULATE); |
5078 } | 5067 } |
5079 if (result_value != NULL) Drop(1); | |
5080 return ast_context()->ReturnValue(Pop()); | 5068 return ast_context()->ReturnValue(Pop()); |
5081 } | 5069 } |
5082 | 5070 |
5083 | 5071 |
5084 void HOptimizedGraphBuilder::HandleCompoundAssignment(Assignment* expr) { | 5072 void HOptimizedGraphBuilder::HandleCompoundAssignment(Assignment* expr) { |
5085 Expression* target = expr->target(); | 5073 Expression* target = expr->target(); |
5086 VariableProxy* proxy = target->AsVariableProxy(); | 5074 VariableProxy* proxy = target->AsVariableProxy(); |
5087 Property* prop = target->AsProperty(); | 5075 Property* prop = target->AsProperty(); |
5088 ASSERT(proxy == NULL || prop == NULL); | 5076 ASSERT(proxy == NULL || prop == NULL); |
5089 | 5077 |
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5200 HValue* right = Pop(); | 5188 HValue* right = Pop(); |
5201 HValue* left = Pop(); | 5189 HValue* left = Pop(); |
5202 | 5190 |
5203 HInstruction* instr = BuildBinaryOperation(operation, left, right); | 5191 HInstruction* instr = BuildBinaryOperation(operation, left, right); |
5204 PushAndAdd(instr); | 5192 PushAndAdd(instr); |
5205 if (instr->HasObservableSideEffects()) { | 5193 if (instr->HasObservableSideEffects()) { |
5206 AddSimulate(operation->id(), REMOVABLE_SIMULATE); | 5194 AddSimulate(operation->id(), REMOVABLE_SIMULATE); |
5207 } | 5195 } |
5208 | 5196 |
5209 return BuildStoreNamed(prop, expr->id(), expr->position(), | 5197 return BuildStoreNamed(prop, expr->id(), expr->position(), |
5210 expr->AssignmentId(), prop, object, instr); | 5198 expr->AssignmentId(), prop, object, instr, instr); |
5211 } else { | 5199 } else { |
5212 // Keyed property. | 5200 // Keyed property. |
5213 CHECK_ALIVE(VisitForValue(prop->obj())); | 5201 CHECK_ALIVE(VisitForValue(prop->obj())); |
5214 CHECK_ALIVE(VisitForValue(prop->key())); | 5202 CHECK_ALIVE(VisitForValue(prop->key())); |
5215 HValue* obj = environment()->ExpressionStackAt(1); | 5203 HValue* obj = environment()->ExpressionStackAt(1); |
5216 HValue* key = environment()->ExpressionStackAt(0); | 5204 HValue* key = environment()->ExpressionStackAt(0); |
5217 | 5205 |
5218 bool has_side_effects = false; | 5206 bool has_side_effects = false; |
5219 HValue* load = HandleKeyedElementAccess( | 5207 HValue* load = HandleKeyedElementAccess( |
5220 obj, key, NULL, prop, prop->LoadId(), RelocInfo::kNoPosition, | 5208 obj, key, NULL, prop, prop->LoadId(), RelocInfo::kNoPosition, |
(...skipping 2472 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7693 } else if (types != NULL && types->length() > 1) { | 7681 } else if (types != NULL && types->length() > 1) { |
7694 load = TryLoadPolymorphicAsMonomorphic(prop, object, types, name); | 7682 load = TryLoadPolymorphicAsMonomorphic(prop, object, types, name); |
7695 } | 7683 } |
7696 if (load == NULL) load = BuildLoadNamedGeneric(object, name, prop); | 7684 if (load == NULL) load = BuildLoadNamedGeneric(object, name, prop); |
7697 PushAndAdd(load); | 7685 PushAndAdd(load); |
7698 if (load->HasObservableSideEffects()) { | 7686 if (load->HasObservableSideEffects()) { |
7699 AddSimulate(prop->LoadId(), REMOVABLE_SIMULATE); | 7687 AddSimulate(prop->LoadId(), REMOVABLE_SIMULATE); |
7700 } | 7688 } |
7701 | 7689 |
7702 after = BuildIncrement(returns_original_input, expr); | 7690 after = BuildIncrement(returns_original_input, expr); |
7703 | 7691 HValue* result = returns_original_input ? Pop() : after; |
7704 HValue* result = returns_original_input ? Pop() : NULL; | |
7705 | 7692 |
7706 return BuildStoreNamed(prop, expr->id(), expr->position(), | 7693 return BuildStoreNamed(prop, expr->id(), expr->position(), |
7707 expr->AssignmentId(), prop, object, after, result); | 7694 expr->AssignmentId(), prop, object, after, result); |
7708 } else { | 7695 } else { |
7709 // Keyed property. | 7696 // Keyed property. |
7710 if (returns_original_input) Push(graph()->GetConstantUndefined()); | 7697 if (returns_original_input) Push(graph()->GetConstantUndefined()); |
7711 | 7698 |
7712 CHECK_ALIVE(VisitForValue(prop->obj())); | 7699 CHECK_ALIVE(VisitForValue(prop->obj())); |
7713 CHECK_ALIVE(VisitForValue(prop->key())); | 7700 CHECK_ALIVE(VisitForValue(prop->key())); |
7714 HValue* obj = environment()->ExpressionStackAt(1); | 7701 HValue* obj = environment()->ExpressionStackAt(1); |
(...skipping 2215 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9930 if (ShouldProduceTraceOutput()) { | 9917 if (ShouldProduceTraceOutput()) { |
9931 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); | 9918 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); |
9932 } | 9919 } |
9933 | 9920 |
9934 #ifdef DEBUG | 9921 #ifdef DEBUG |
9935 graph_->Verify(false); // No full verify. | 9922 graph_->Verify(false); // No full verify. |
9936 #endif | 9923 #endif |
9937 } | 9924 } |
9938 | 9925 |
9939 } } // namespace v8::internal | 9926 } } // namespace v8::internal |
OLD | NEW |