| 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 |