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