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 4878 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4889 | 4889 |
4890 ASSERT(join != NULL); | 4890 ASSERT(join != NULL); |
4891 join->SetJoinId(assignment_id); | 4891 join->SetJoinId(assignment_id); |
4892 set_current_block(join); | 4892 set_current_block(join); |
4893 if (!ast_context()->IsEffect()) { | 4893 if (!ast_context()->IsEffect()) { |
4894 ast_context()->ReturnValue(Pop()); | 4894 ast_context()->ReturnValue(Pop()); |
4895 } | 4895 } |
4896 } | 4896 } |
4897 | 4897 |
4898 | 4898 |
4899 void HOptimizedGraphBuilder::HandlePropertyAssignment(Assignment* expr) { | |
4900 Property* prop = expr->target()->AsProperty(); | |
4901 ASSERT(prop != NULL); | |
4902 CHECK_ALIVE(VisitForValue(prop->obj())); | |
4903 | |
4904 if (prop->key()->IsPropertyName()) { | |
4905 // Named store. | |
4906 CHECK_ALIVE(VisitForValue(expr->value())); | |
4907 HValue* value = environment()->ExpressionStackAt(0); | |
4908 HValue* object = environment()->ExpressionStackAt(1); | |
4909 | |
4910 if (expr->IsUninitialized()) { | |
4911 Add<HDeoptimize>("Insufficient type feedback for property assignment", | |
4912 Deoptimizer::SOFT); | |
4913 } | |
4914 return BuildStoreNamed( | |
4915 expr, expr->id(), expr->AssignmentId(), prop, object, value); | |
4916 } else { | |
4917 // Keyed store. | |
4918 CHECK_ALIVE(VisitForValue(prop->key())); | |
4919 CHECK_ALIVE(VisitForValue(expr->value())); | |
4920 HValue* value = environment()->ExpressionStackAt(0); | |
4921 HValue* key = environment()->ExpressionStackAt(1); | |
4922 HValue* object = environment()->ExpressionStackAt(2); | |
4923 bool has_side_effects = false; | |
4924 HandleKeyedElementAccess(object, key, value, expr, expr->AssignmentId(), | |
4925 expr->position(), | |
4926 true, // is_store | |
4927 &has_side_effects); | |
4928 Drop(3); | |
4929 Push(value); | |
4930 Add<HSimulate>(expr->AssignmentId(), REMOVABLE_SIMULATE); | |
4931 return ast_context()->ReturnValue(Pop()); | |
4932 } | |
4933 } | |
4934 | |
4935 | |
4936 // Because not every expression has a position and there is not common | |
4937 // superclass of Assignment and CountOperation, we cannot just pass the | |
4938 // owning expression instead of position and ast_id separately. | |
4939 void HOptimizedGraphBuilder::HandleGlobalVariableAssignment( | |
4940 Variable* var, | |
4941 HValue* value, | |
4942 int position, | |
4943 BailoutId ast_id) { | |
4944 LookupResult lookup(isolate()); | |
4945 GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, true); | |
4946 if (type == kUseCell) { | |
4947 Handle<GlobalObject> global(current_info()->global_object()); | |
4948 Handle<PropertyCell> cell(global->GetPropertyCell(&lookup)); | |
4949 if (cell->type()->IsConstant()) { | |
4950 IfBuilder builder(this); | |
4951 HValue* constant = Add<HConstant>(cell->type()->AsConstant()); | |
4952 if (cell->type()->AsConstant()->IsNumber()) { | |
4953 builder.If<HCompareNumericAndBranch>(value, constant, Token::EQ); | |
4954 } else { | |
4955 builder.If<HCompareObjectEqAndBranch>(value, constant); | |
4956 } | |
4957 builder.Then(); | |
4958 builder.Else(); | |
4959 Add<HDeoptimize>("Constant global variable assignment", | |
4960 Deoptimizer::EAGER); | |
4961 builder.End(); | |
4962 } | |
4963 HInstruction* instr = | |
4964 Add<HStoreGlobalCell>(value, cell, lookup.GetPropertyDetails()); | |
4965 instr->set_position(position); | |
4966 if (instr->HasObservableSideEffects()) { | |
4967 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); | |
4968 } | |
4969 } else { | |
4970 HGlobalObject* global_object = Add<HGlobalObject>(); | |
4971 HStoreGlobalGeneric* instr = | |
4972 Add<HStoreGlobalGeneric>(global_object, var->name(), | |
4973 value, function_strict_mode_flag()); | |
4974 instr->set_position(position); | |
4975 ASSERT(instr->HasObservableSideEffects()); | |
4976 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); | |
4977 } | |
4978 } | |
4979 | |
4980 | |
4981 static bool ComputeReceiverTypes(Expression* expr, | 4899 static bool ComputeReceiverTypes(Expression* expr, |
4982 HValue* receiver, | 4900 HValue* receiver, |
4983 SmallMapList** t) { | 4901 SmallMapList** t) { |
4984 SmallMapList* types = expr->GetReceiverTypes(); | 4902 SmallMapList* types = expr->GetReceiverTypes(); |
4985 *t = types; | 4903 *t = types; |
4986 bool monomorphic = expr->IsMonomorphic(); | 4904 bool monomorphic = expr->IsMonomorphic(); |
4987 if (types != NULL && receiver->HasMonomorphicJSObjectType()) { | 4905 if (types != NULL && receiver->HasMonomorphicJSObjectType()) { |
4988 Map* root_map = receiver->GetMonomorphicJSObjectMap()->FindRootMap(); | 4906 Map* root_map = receiver->GetMonomorphicJSObjectMap()->FindRootMap(); |
4989 types->FilterForPossibleTransitions(root_map); | 4907 types->FilterForPossibleTransitions(root_map); |
4990 monomorphic = types->length() == 1; | 4908 monomorphic = types->length() == 1; |
4991 } | 4909 } |
4992 return monomorphic && CanInlinePropertyAccess(*types->first()); | 4910 return monomorphic && CanInlinePropertyAccess(*types->first()); |
4993 } | 4911 } |
4994 | 4912 |
4995 | 4913 |
4996 void HOptimizedGraphBuilder::BuildStoreNamed(Expression* expr, | 4914 void HOptimizedGraphBuilder::BuildStore(Expression* expr, |
4997 BailoutId id, | 4915 Property* prop, |
4998 BailoutId assignment_id, | 4916 BailoutId ast_id, |
4999 Property* prop, | 4917 BailoutId return_id, |
5000 HValue* object, | 4918 bool is_uninitialized) { |
5001 HValue* value) { | 4919 HValue* value = environment()->ExpressionStackAt(0); |
| 4920 |
| 4921 if (!prop->key()->IsPropertyName()) { |
| 4922 // Keyed store. |
| 4923 HValue* key = environment()->ExpressionStackAt(1); |
| 4924 HValue* object = environment()->ExpressionStackAt(2); |
| 4925 bool has_side_effects = false; |
| 4926 HandleKeyedElementAccess(object, key, value, expr, return_id, |
| 4927 expr->position(), |
| 4928 true, // is_store |
| 4929 &has_side_effects); |
| 4930 Drop(3); |
| 4931 Push(value); |
| 4932 Add<HSimulate>(return_id, REMOVABLE_SIMULATE); |
| 4933 return ast_context()->ReturnValue(Pop()); |
| 4934 } |
| 4935 |
| 4936 // Named store. |
| 4937 HValue* object = environment()->ExpressionStackAt(1); |
| 4938 |
| 4939 if (is_uninitialized) { |
| 4940 Add<HDeoptimize>("Insufficient type feedback for property assignment", |
| 4941 Deoptimizer::SOFT); |
| 4942 } |
| 4943 |
5002 Literal* key = prop->key()->AsLiteral(); | 4944 Literal* key = prop->key()->AsLiteral(); |
5003 Handle<String> name = Handle<String>::cast(key->value()); | 4945 Handle<String> name = Handle<String>::cast(key->value()); |
5004 ASSERT(!name.is_null()); | 4946 ASSERT(!name.is_null()); |
5005 | 4947 |
5006 HInstruction* instr = NULL; | 4948 HInstruction* instr = NULL; |
5007 | 4949 |
5008 SmallMapList* types; | 4950 SmallMapList* types; |
5009 bool monomorphic = ComputeReceiverTypes(expr, object, &types); | 4951 bool monomorphic = ComputeReceiverTypes(expr, object, &types); |
5010 | 4952 |
5011 if (monomorphic) { | 4953 if (monomorphic) { |
5012 Handle<Map> map = types->first(); | 4954 Handle<Map> map = types->first(); |
5013 Handle<JSFunction> setter; | 4955 Handle<JSFunction> setter; |
5014 Handle<JSObject> holder; | 4956 Handle<JSObject> holder; |
5015 if (LookupSetter(map, name, &setter, &holder)) { | 4957 if (LookupSetter(map, name, &setter, &holder)) { |
5016 AddCheckConstantFunction(holder, object, map); | 4958 AddCheckConstantFunction(holder, object, map); |
5017 if (FLAG_inline_accessors && | 4959 if (FLAG_inline_accessors && |
5018 TryInlineSetter(setter, id, assignment_id, value)) { | 4960 TryInlineSetter(setter, ast_id, return_id, value)) { |
5019 return; | 4961 return; |
5020 } | 4962 } |
5021 Drop(2); | 4963 Drop(2); |
5022 Add<HPushArgument>(object); | 4964 Add<HPushArgument>(object); |
5023 Add<HPushArgument>(value); | 4965 Add<HPushArgument>(value); |
5024 instr = new(zone()) HCallConstantFunction(setter, 2); | 4966 instr = new(zone()) HCallConstantFunction(setter, 2); |
5025 } else { | 4967 } else { |
5026 Drop(2); | 4968 Drop(2); |
5027 CHECK_ALIVE(instr = BuildStoreNamedMonomorphic(object, | 4969 CHECK_ALIVE(instr = BuildStoreNamedMonomorphic(object, |
5028 name, | 4970 name, |
5029 value, | 4971 value, |
5030 map)); | 4972 map)); |
5031 } | 4973 } |
5032 } else if (types != NULL && types->length() > 1) { | 4974 } else if (types != NULL && types->length() > 1) { |
5033 Drop(2); | 4975 Drop(2); |
5034 return HandlePolymorphicStoreNamedField( | 4976 return HandlePolymorphicStoreNamedField( |
5035 expr->position(), id, object, value, types, name); | 4977 expr->position(), ast_id, object, value, types, name); |
5036 } else { | 4978 } else { |
5037 Drop(2); | 4979 Drop(2); |
5038 instr = BuildStoreNamedGeneric(object, name, value); | 4980 instr = BuildStoreNamedGeneric(object, name, value); |
5039 } | 4981 } |
5040 | 4982 |
5041 if (!ast_context()->IsEffect()) Push(value); | 4983 if (!ast_context()->IsEffect()) Push(value); |
5042 instr->set_position(expr->position()); | 4984 instr->set_position(expr->position()); |
5043 AddInstruction(instr); | 4985 AddInstruction(instr); |
5044 if (instr->HasObservableSideEffects()) { | 4986 if (instr->HasObservableSideEffects()) { |
5045 Add<HSimulate>(id, REMOVABLE_SIMULATE); | 4987 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); |
5046 } | 4988 } |
5047 if (!ast_context()->IsEffect()) Drop(1); | 4989 if (!ast_context()->IsEffect()) Drop(1); |
5048 return ast_context()->ReturnValue(value); | 4990 return ast_context()->ReturnValue(value); |
5049 } | 4991 } |
5050 | 4992 |
5051 | 4993 |
| 4994 void HOptimizedGraphBuilder::HandlePropertyAssignment(Assignment* expr) { |
| 4995 Property* prop = expr->target()->AsProperty(); |
| 4996 ASSERT(prop != NULL); |
| 4997 CHECK_ALIVE(VisitForValue(prop->obj())); |
| 4998 if (!prop->key()->IsPropertyName()) { |
| 4999 CHECK_ALIVE(VisitForValue(prop->key())); |
| 5000 } |
| 5001 CHECK_ALIVE(VisitForValue(expr->value())); |
| 5002 BuildStore(expr, prop, expr->id(), |
| 5003 expr->AssignmentId(), expr->IsUninitialized()); |
| 5004 } |
| 5005 |
| 5006 |
| 5007 // Because not every expression has a position and there is not common |
| 5008 // superclass of Assignment and CountOperation, we cannot just pass the |
| 5009 // owning expression instead of position and ast_id separately. |
| 5010 void HOptimizedGraphBuilder::HandleGlobalVariableAssignment( |
| 5011 Variable* var, |
| 5012 HValue* value, |
| 5013 int position, |
| 5014 BailoutId ast_id) { |
| 5015 LookupResult lookup(isolate()); |
| 5016 GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, true); |
| 5017 if (type == kUseCell) { |
| 5018 Handle<GlobalObject> global(current_info()->global_object()); |
| 5019 Handle<PropertyCell> cell(global->GetPropertyCell(&lookup)); |
| 5020 if (cell->type()->IsConstant()) { |
| 5021 IfBuilder builder(this); |
| 5022 HValue* constant = Add<HConstant>(cell->type()->AsConstant()); |
| 5023 if (cell->type()->AsConstant()->IsNumber()) { |
| 5024 builder.If<HCompareNumericAndBranch>(value, constant, Token::EQ); |
| 5025 } else { |
| 5026 builder.If<HCompareObjectEqAndBranch>(value, constant); |
| 5027 } |
| 5028 builder.Then(); |
| 5029 builder.Else(); |
| 5030 Add<HDeoptimize>("Constant global variable assignment", |
| 5031 Deoptimizer::EAGER); |
| 5032 builder.End(); |
| 5033 } |
| 5034 HInstruction* instr = |
| 5035 Add<HStoreGlobalCell>(value, cell, lookup.GetPropertyDetails()); |
| 5036 instr->set_position(position); |
| 5037 if (instr->HasObservableSideEffects()) { |
| 5038 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); |
| 5039 } |
| 5040 } else { |
| 5041 HGlobalObject* global_object = Add<HGlobalObject>(); |
| 5042 HStoreGlobalGeneric* instr = |
| 5043 Add<HStoreGlobalGeneric>(global_object, var->name(), |
| 5044 value, function_strict_mode_flag()); |
| 5045 instr->set_position(position); |
| 5046 ASSERT(instr->HasObservableSideEffects()); |
| 5047 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); |
| 5048 } |
| 5049 } |
| 5050 |
| 5051 |
5052 void HOptimizedGraphBuilder::HandleCompoundAssignment(Assignment* expr) { | 5052 void HOptimizedGraphBuilder::HandleCompoundAssignment(Assignment* expr) { |
5053 Expression* target = expr->target(); | 5053 Expression* target = expr->target(); |
5054 VariableProxy* proxy = target->AsVariableProxy(); | 5054 VariableProxy* proxy = target->AsVariableProxy(); |
5055 Property* prop = target->AsProperty(); | 5055 Property* prop = target->AsProperty(); |
5056 ASSERT(proxy == NULL || prop == NULL); | 5056 ASSERT(proxy == NULL || prop == NULL); |
5057 | 5057 |
5058 // We have a second position recorded in the FullCodeGenerator to have | 5058 // We have a second position recorded in the FullCodeGenerator to have |
5059 // type feedback for the binary operation. | 5059 // type feedback for the binary operation. |
5060 BinaryOperation* operation = expr->binary_operation(); | 5060 BinaryOperation* operation = expr->binary_operation(); |
5061 | 5061 |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5123 } | 5123 } |
5124 break; | 5124 break; |
5125 } | 5125 } |
5126 | 5126 |
5127 case Variable::LOOKUP: | 5127 case Variable::LOOKUP: |
5128 return Bailout(kCompoundAssignmentToLookupSlot); | 5128 return Bailout(kCompoundAssignmentToLookupSlot); |
5129 } | 5129 } |
5130 return ast_context()->ReturnValue(Pop()); | 5130 return ast_context()->ReturnValue(Pop()); |
5131 | 5131 |
5132 } else if (prop != NULL) { | 5132 } else if (prop != NULL) { |
5133 if (prop->key()->IsPropertyName()) { | 5133 CHECK_ALIVE(VisitForValue(prop->obj())); |
5134 // Named property. | 5134 HValue* object = Top(); |
5135 CHECK_ALIVE(VisitForValue(prop->obj())); | 5135 HValue* key = NULL; |
5136 HValue* object = Top(); | 5136 if ((!prop->IsStringLength() && |
5137 CHECK_ALIVE(PushLoad(prop, object, expr->position())); | 5137 !prop->IsFunctionPrototype() && |
5138 | 5138 !prop->key()->IsPropertyName()) || |
5139 CHECK_ALIVE(VisitForValue(expr->value())); | 5139 prop->IsStringAccess()) { |
5140 HValue* right = Pop(); | |
5141 HValue* left = Pop(); | |
5142 | |
5143 HInstruction* instr = BuildBinaryOperation(operation, left, right); | |
5144 PushAndAdd(instr); | |
5145 if (instr->HasObservableSideEffects()) { | |
5146 Add<HSimulate>(operation->id(), REMOVABLE_SIMULATE); | |
5147 } | |
5148 | |
5149 return BuildStoreNamed( | |
5150 expr, expr->id(), expr->AssignmentId(), prop, object, instr); | |
5151 } else { | |
5152 // Keyed property. | |
5153 CHECK_ALIVE(VisitForValue(prop->obj())); | |
5154 CHECK_ALIVE(VisitForValue(prop->key())); | 5140 CHECK_ALIVE(VisitForValue(prop->key())); |
5155 HValue* obj = environment()->ExpressionStackAt(1); | 5141 key = Top(); |
5156 HValue* key = environment()->ExpressionStackAt(0); | |
5157 | |
5158 bool has_side_effects = false; | |
5159 HValue* load = HandleKeyedElementAccess( | |
5160 obj, key, NULL, prop, prop->LoadId(), RelocInfo::kNoPosition, | |
5161 false, // is_store | |
5162 &has_side_effects); | |
5163 Push(load); | |
5164 if (has_side_effects) Add<HSimulate>(prop->LoadId(), REMOVABLE_SIMULATE); | |
5165 | |
5166 CHECK_ALIVE(VisitForValue(expr->value())); | |
5167 HValue* right = Pop(); | |
5168 HValue* left = Pop(); | |
5169 | |
5170 HInstruction* instr = BuildBinaryOperation(operation, left, right); | |
5171 PushAndAdd(instr); | |
5172 if (instr->HasObservableSideEffects()) { | |
5173 Add<HSimulate>(operation->id(), REMOVABLE_SIMULATE); | |
5174 } | |
5175 | |
5176 HandleKeyedElementAccess(obj, key, instr, expr, expr->AssignmentId(), | |
5177 RelocInfo::kNoPosition, | |
5178 true, // is_store | |
5179 &has_side_effects); | |
5180 | |
5181 // Drop the simulated receiver, key, and value. Return the value. | |
5182 Drop(3); | |
5183 Push(instr); | |
5184 ASSERT(has_side_effects); // Stores always have side effects. | |
5185 Add<HSimulate>(expr->AssignmentId(), REMOVABLE_SIMULATE); | |
5186 return ast_context()->ReturnValue(Pop()); | |
5187 } | 5142 } |
5188 | 5143 |
| 5144 CHECK_ALIVE(PushLoad(prop, object, key, expr->position())); |
| 5145 |
| 5146 CHECK_ALIVE(VisitForValue(expr->value())); |
| 5147 HValue* right = Pop(); |
| 5148 HValue* left = Pop(); |
| 5149 |
| 5150 HInstruction* instr = BuildBinaryOperation(operation, left, right); |
| 5151 PushAndAdd(instr); |
| 5152 if (instr->HasObservableSideEffects()) { |
| 5153 Add<HSimulate>(operation->id(), REMOVABLE_SIMULATE); |
| 5154 } |
| 5155 BuildStore(expr, prop, expr->id(), |
| 5156 expr->AssignmentId(), expr->IsUninitialized()); |
5189 } else { | 5157 } else { |
5190 return Bailout(kInvalidLhsInCompoundAssignment); | 5158 return Bailout(kInvalidLhsInCompoundAssignment); |
5191 } | 5159 } |
5192 } | 5160 } |
5193 | 5161 |
5194 | 5162 |
5195 void HOptimizedGraphBuilder::VisitAssignment(Assignment* expr) { | 5163 void HOptimizedGraphBuilder::VisitAssignment(Assignment* expr) { |
5196 ASSERT(!HasStackOverflow()); | 5164 ASSERT(!HasStackOverflow()); |
5197 ASSERT(current_block() != NULL); | 5165 ASSERT(current_block() != NULL); |
5198 ASSERT(current_block()->HasPredecessor()); | 5166 ASSERT(current_block()->HasPredecessor()); |
(...skipping 634 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5833 result = new(zone()) HAccessArgumentsAt(elements, length, checked_key); | 5801 result = new(zone()) HAccessArgumentsAt(elements, length, checked_key); |
5834 } | 5802 } |
5835 } | 5803 } |
5836 ast_context()->ReturnInstruction(result, expr->id()); | 5804 ast_context()->ReturnInstruction(result, expr->id()); |
5837 return true; | 5805 return true; |
5838 } | 5806 } |
5839 | 5807 |
5840 | 5808 |
5841 void HOptimizedGraphBuilder::PushLoad(Property* expr, | 5809 void HOptimizedGraphBuilder::PushLoad(Property* expr, |
5842 HValue* object, | 5810 HValue* object, |
| 5811 HValue* key, |
5843 int position) { | 5812 int position) { |
5844 ValueContext for_value(this, ARGUMENTS_NOT_ALLOWED); | 5813 ValueContext for_value(this, ARGUMENTS_NOT_ALLOWED); |
5845 Push(object); | 5814 Push(object); |
| 5815 if (key != NULL) Push(key); |
5846 BuildLoad(expr, position, expr->LoadId()); | 5816 BuildLoad(expr, position, expr->LoadId()); |
5847 } | 5817 } |
5848 | 5818 |
5849 | 5819 |
5850 void HOptimizedGraphBuilder::BuildLoad(Property* expr, | 5820 void HOptimizedGraphBuilder::BuildLoad(Property* expr, |
5851 int position, | 5821 int position, |
5852 BailoutId ast_id) { | 5822 BailoutId ast_id) { |
5853 HInstruction* instr = NULL; | 5823 HInstruction* instr = NULL; |
5854 if (expr->IsStringLength()) { | 5824 if (expr->IsStringLength()) { |
5855 HValue* string = Pop(); | 5825 HValue* string = Pop(); |
5856 BuildCheckHeapObject(string); | 5826 BuildCheckHeapObject(string); |
5857 HInstruction* checkstring = | 5827 HInstruction* checkstring = |
5858 AddInstruction(HCheckInstanceType::NewIsString(string, zone())); | 5828 AddInstruction(HCheckInstanceType::NewIsString(string, zone())); |
5859 instr = BuildLoadStringLength(string, checkstring); | 5829 instr = BuildLoadStringLength(string, checkstring); |
5860 } else if (expr->IsStringAccess()) { | 5830 } else if (expr->IsStringAccess()) { |
5861 CHECK_ALIVE(VisitForValue(expr->key())); | |
5862 HValue* index = Pop(); | 5831 HValue* index = Pop(); |
5863 HValue* string = Pop(); | 5832 HValue* string = Pop(); |
5864 HValue* context = environment()->context(); | 5833 HValue* context = environment()->context(); |
5865 HInstruction* char_code = | 5834 HInstruction* char_code = |
5866 BuildStringCharCodeAt(string, index); | 5835 BuildStringCharCodeAt(string, index); |
5867 AddInstruction(char_code); | 5836 AddInstruction(char_code); |
5868 instr = HStringCharFromCode::New(zone(), context, char_code); | 5837 instr = HStringCharFromCode::New(zone(), context, char_code); |
5869 | 5838 |
5870 } else if (expr->IsFunctionPrototype()) { | 5839 } else if (expr->IsFunctionPrototype()) { |
5871 HValue* function = Pop(); | 5840 HValue* function = Pop(); |
(...skipping 23 matching lines...) Expand all Loading... |
5895 instr = BuildLoadNamedMonomorphic(Pop(), name, map); | 5864 instr = BuildLoadNamedMonomorphic(Pop(), name, map); |
5896 } | 5865 } |
5897 } else if (types != NULL && types->length() > 1) { | 5866 } else if (types != NULL && types->length() > 1) { |
5898 return HandlePolymorphicLoadNamedField( | 5867 return HandlePolymorphicLoadNamedField( |
5899 position, ast_id, Pop(), types, name); | 5868 position, ast_id, Pop(), types, name); |
5900 } else { | 5869 } else { |
5901 instr = BuildLoadNamedGeneric(Pop(), name, expr); | 5870 instr = BuildLoadNamedGeneric(Pop(), name, expr); |
5902 } | 5871 } |
5903 | 5872 |
5904 } else { | 5873 } else { |
5905 CHECK_ALIVE(VisitForValue(expr->key())); | |
5906 | |
5907 HValue* key = Pop(); | 5874 HValue* key = Pop(); |
5908 HValue* obj = Pop(); | 5875 HValue* obj = Pop(); |
5909 | 5876 |
5910 bool has_side_effects = false; | 5877 bool has_side_effects = false; |
5911 HValue* load = HandleKeyedElementAccess( | 5878 HValue* load = HandleKeyedElementAccess( |
5912 obj, key, NULL, expr, ast_id, position, | 5879 obj, key, NULL, expr, ast_id, position, |
5913 false, // is_store | 5880 false, // is_store |
5914 &has_side_effects); | 5881 &has_side_effects); |
5915 if (has_side_effects) { | 5882 if (has_side_effects) { |
5916 if (ast_context()->IsEffect()) { | 5883 if (ast_context()->IsEffect()) { |
(...skipping 12 matching lines...) Expand all Loading... |
5929 | 5896 |
5930 | 5897 |
5931 void HOptimizedGraphBuilder::VisitProperty(Property* expr) { | 5898 void HOptimizedGraphBuilder::VisitProperty(Property* expr) { |
5932 ASSERT(!HasStackOverflow()); | 5899 ASSERT(!HasStackOverflow()); |
5933 ASSERT(current_block() != NULL); | 5900 ASSERT(current_block() != NULL); |
5934 ASSERT(current_block()->HasPredecessor()); | 5901 ASSERT(current_block()->HasPredecessor()); |
5935 | 5902 |
5936 if (TryArgumentsAccess(expr)) return; | 5903 if (TryArgumentsAccess(expr)) return; |
5937 | 5904 |
5938 CHECK_ALIVE(VisitForValue(expr->obj())); | 5905 CHECK_ALIVE(VisitForValue(expr->obj())); |
| 5906 if ((!expr->IsStringLength() && |
| 5907 !expr->IsFunctionPrototype() && |
| 5908 !expr->key()->IsPropertyName()) || |
| 5909 expr->IsStringAccess()) { |
| 5910 CHECK_ALIVE(VisitForValue(expr->key())); |
| 5911 } |
| 5912 |
5939 BuildLoad(expr, expr->position(), expr->id()); | 5913 BuildLoad(expr, expr->position(), expr->id()); |
5940 } | 5914 } |
5941 | 5915 |
5942 | 5916 |
5943 HInstruction* HGraphBuilder::BuildConstantMapCheck(Handle<JSObject> constant, | 5917 HInstruction* HGraphBuilder::BuildConstantMapCheck(Handle<JSObject> constant, |
5944 CompilationInfo* info) { | 5918 CompilationInfo* info) { |
5945 HConstant* constant_value = New<HConstant>(constant); | 5919 HConstant* constant_value = New<HConstant>(constant); |
5946 | 5920 |
5947 if (constant->map()->CanOmitMapChecks()) { | 5921 if (constant->map()->CanOmitMapChecks()) { |
5948 constant->map()->AddDependentCompilationInfo( | 5922 constant->map()->AddDependentCompilationInfo( |
(...skipping 1522 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7471 HAdd* add = HAdd::cast(instr); | 7445 HAdd* add = HAdd::cast(instr); |
7472 add->set_observed_input_representation(1, rep); | 7446 add->set_observed_input_representation(1, rep); |
7473 add->set_observed_input_representation(2, Representation::Smi()); | 7447 add->set_observed_input_representation(2, Representation::Smi()); |
7474 } | 7448 } |
7475 instr->SetFlag(HInstruction::kCannotBeTagged); | 7449 instr->SetFlag(HInstruction::kCannotBeTagged); |
7476 instr->ClearAllSideEffects(); | 7450 instr->ClearAllSideEffects(); |
7477 return instr; | 7451 return instr; |
7478 } | 7452 } |
7479 | 7453 |
7480 | 7454 |
7481 void HOptimizedGraphBuilder::BuildStoreInEffect(Expression* expr, | 7455 void HOptimizedGraphBuilder::BuildStoreForEffect(Expression* expr, |
7482 Property* prop, | 7456 Property* prop, |
7483 BailoutId ast_id, | 7457 BailoutId ast_id, |
7484 BailoutId return_id, | 7458 BailoutId return_id, |
7485 HValue* object, | 7459 HValue* object, |
7486 HValue* value) { | 7460 HValue* key, |
| 7461 HValue* value) { |
7487 EffectContext for_effect(this); | 7462 EffectContext for_effect(this); |
7488 Push(object); | 7463 Push(object); |
| 7464 if (key != NULL) Push(key); |
7489 Push(value); | 7465 Push(value); |
7490 BuildStoreNamed(expr, ast_id, return_id, prop, object, value); | 7466 BuildStore(expr, prop, ast_id, return_id); |
7491 } | 7467 } |
7492 | 7468 |
7493 | 7469 |
7494 void HOptimizedGraphBuilder::VisitCountOperation(CountOperation* expr) { | 7470 void HOptimizedGraphBuilder::VisitCountOperation(CountOperation* expr) { |
7495 ASSERT(!HasStackOverflow()); | 7471 ASSERT(!HasStackOverflow()); |
7496 ASSERT(current_block() != NULL); | 7472 ASSERT(current_block() != NULL); |
7497 ASSERT(current_block()->HasPredecessor()); | 7473 ASSERT(current_block()->HasPredecessor()); |
7498 Expression* target = expr->expression(); | 7474 Expression* target = expr->expression(); |
7499 VariableProxy* proxy = target->AsVariableProxy(); | 7475 VariableProxy* proxy = target->AsVariableProxy(); |
7500 Property* prop = target->AsProperty(); | 7476 Property* prop = target->AsProperty(); |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7560 if (instr->HasObservableSideEffects()) { | 7536 if (instr->HasObservableSideEffects()) { |
7561 Add<HSimulate>(expr->AssignmentId(), REMOVABLE_SIMULATE); | 7537 Add<HSimulate>(expr->AssignmentId(), REMOVABLE_SIMULATE); |
7562 } | 7538 } |
7563 break; | 7539 break; |
7564 } | 7540 } |
7565 | 7541 |
7566 case Variable::LOOKUP: | 7542 case Variable::LOOKUP: |
7567 return Bailout(kLookupVariableInCountOperation); | 7543 return Bailout(kLookupVariableInCountOperation); |
7568 } | 7544 } |
7569 | 7545 |
7570 } else { | 7546 Drop(returns_original_input ? 2 : 1); |
7571 // Argument of the count operation is a property. | 7547 return ast_context()->ReturnValue(expr->is_postfix() ? input : after); |
7572 ASSERT(prop != NULL); | |
7573 | |
7574 if (prop->key()->IsPropertyName()) { | |
7575 // Named property. | |
7576 if (returns_original_input) Push(graph()->GetConstantUndefined()); | |
7577 | |
7578 CHECK_ALIVE(VisitForValue(prop->obj())); | |
7579 HValue* object = Top(); | |
7580 CHECK_ALIVE(PushLoad(prop, object, expr->position())); | |
7581 | |
7582 after = BuildIncrement(returns_original_input, expr); | |
7583 | |
7584 if (returns_original_input) { | |
7585 HValue* result = Pop(); | |
7586 HValue* object = Pop(); | |
7587 environment()->SetExpressionStackAt(0, result); | |
7588 CHECK_ALIVE(BuildStoreInEffect( | |
7589 expr, prop, expr->id(), expr->AssignmentId(), object, after)); | |
7590 return ast_context()->ReturnValue(Pop()); | |
7591 } | |
7592 | |
7593 return BuildStoreNamed( | |
7594 expr, expr->id(), expr->AssignmentId(), prop, object, after); | |
7595 } else { | |
7596 // Keyed property. | |
7597 if (returns_original_input) Push(graph()->GetConstantUndefined()); | |
7598 | |
7599 CHECK_ALIVE(VisitForValue(prop->obj())); | |
7600 CHECK_ALIVE(VisitForValue(prop->key())); | |
7601 HValue* obj = environment()->ExpressionStackAt(1); | |
7602 HValue* key = environment()->ExpressionStackAt(0); | |
7603 | |
7604 bool has_side_effects = false; | |
7605 HValue* load = HandleKeyedElementAccess( | |
7606 obj, key, NULL, prop, prop->LoadId(), RelocInfo::kNoPosition, | |
7607 false, // is_store | |
7608 &has_side_effects); | |
7609 Push(load); | |
7610 if (has_side_effects) Add<HSimulate>(prop->LoadId(), REMOVABLE_SIMULATE); | |
7611 | |
7612 after = BuildIncrement(returns_original_input, expr); | |
7613 input = environment()->ExpressionStackAt(0); | |
7614 | |
7615 HandleKeyedElementAccess(obj, key, after, expr, expr->AssignmentId(), | |
7616 RelocInfo::kNoPosition, | |
7617 true, // is_store | |
7618 &has_side_effects); | |
7619 | |
7620 // Drop the key and the original value from the bailout environment. | |
7621 // Overwrite the receiver with the result of the operation, and the | |
7622 // placeholder with the original value if necessary. | |
7623 Drop(2); | |
7624 environment()->SetExpressionStackAt(0, after); | |
7625 if (returns_original_input) environment()->SetExpressionStackAt(1, input); | |
7626 ASSERT(has_side_effects); // Stores always have side effects. | |
7627 Add<HSimulate>(expr->AssignmentId(), REMOVABLE_SIMULATE); | |
7628 } | |
7629 } | 7548 } |
7630 | 7549 |
7631 Drop(returns_original_input ? 2 : 1); | 7550 // Argument of the count operation is a property. |
7632 return ast_context()->ReturnValue(expr->is_postfix() ? input : after); | 7551 ASSERT(prop != NULL); |
| 7552 if (returns_original_input) Push(graph()->GetConstantUndefined()); |
| 7553 |
| 7554 CHECK_ALIVE(VisitForValue(prop->obj())); |
| 7555 HValue* object = Top(); |
| 7556 |
| 7557 HValue* key = NULL; |
| 7558 if ((!prop->IsStringLength() && |
| 7559 !prop->IsFunctionPrototype() && |
| 7560 !prop->key()->IsPropertyName()) || |
| 7561 prop->IsStringAccess()) { |
| 7562 CHECK_ALIVE(VisitForValue(prop->key())); |
| 7563 key = Top(); |
| 7564 } |
| 7565 |
| 7566 CHECK_ALIVE(PushLoad(prop, object, key, expr->position())); |
| 7567 |
| 7568 after = BuildIncrement(returns_original_input, expr); |
| 7569 |
| 7570 if (returns_original_input) { |
| 7571 input = Pop(); |
| 7572 // Drop object and key to push it again in the effect context below. |
| 7573 Drop(key == NULL ? 1 : 2); |
| 7574 environment()->SetExpressionStackAt(0, input); |
| 7575 CHECK_ALIVE(BuildStoreForEffect( |
| 7576 expr, prop, expr->id(), expr->AssignmentId(), object, key, after)); |
| 7577 return ast_context()->ReturnValue(Pop()); |
| 7578 } |
| 7579 |
| 7580 environment()->SetExpressionStackAt(0, after); |
| 7581 return BuildStore(expr, prop, expr->id(), expr->AssignmentId()); |
7633 } | 7582 } |
7634 | 7583 |
7635 | 7584 |
7636 HInstruction* HOptimizedGraphBuilder::BuildStringCharCodeAt( | 7585 HInstruction* HOptimizedGraphBuilder::BuildStringCharCodeAt( |
7637 HValue* string, | 7586 HValue* string, |
7638 HValue* index) { | 7587 HValue* index) { |
7639 if (string->IsConstant() && index->IsConstant()) { | 7588 if (string->IsConstant() && index->IsConstant()) { |
7640 HConstant* c_string = HConstant::cast(string); | 7589 HConstant* c_string = HConstant::cast(string); |
7641 HConstant* c_index = HConstant::cast(index); | 7590 HConstant* c_index = HConstant::cast(index); |
7642 if (c_string->HasStringValue() && c_index->HasNumberValue()) { | 7591 if (c_string->HasStringValue() && c_index->HasNumberValue()) { |
(...skipping 2083 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9726 if (ShouldProduceTraceOutput()) { | 9675 if (ShouldProduceTraceOutput()) { |
9727 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); | 9676 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); |
9728 } | 9677 } |
9729 | 9678 |
9730 #ifdef DEBUG | 9679 #ifdef DEBUG |
9731 graph_->Verify(false); // No full verify. | 9680 graph_->Verify(false); // No full verify. |
9732 #endif | 9681 #endif |
9733 } | 9682 } |
9734 | 9683 |
9735 } } // namespace v8::internal | 9684 } } // namespace v8::internal |
OLD | NEW |