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 5053 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5064 case ObjectLiteral::Property::COMPUTED: | 5064 case ObjectLiteral::Property::COMPUTED: |
5065 if (key->value()->IsInternalizedString()) { | 5065 if (key->value()->IsInternalizedString()) { |
5066 if (property->emit_store()) { | 5066 if (property->emit_store()) { |
5067 CHECK_ALIVE(VisitForValue(value)); | 5067 CHECK_ALIVE(VisitForValue(value)); |
5068 HValue* value = Pop(); | 5068 HValue* value = Pop(); |
5069 Handle<Map> map = property->GetReceiverType(); | 5069 Handle<Map> map = property->GetReceiverType(); |
5070 Handle<String> name = property->key()->AsPropertyName(); | 5070 Handle<String> name = property->key()->AsPropertyName(); |
5071 HInstruction* store; | 5071 HInstruction* store; |
5072 if (map.is_null()) { | 5072 if (map.is_null()) { |
5073 // If we don't know the monomorphic type, do a generic store. | 5073 // If we don't know the monomorphic type, do a generic store. |
5074 CHECK_ALIVE(store = BuildStoreNamedGeneric(literal, name, value)); | 5074 CHECK_ALIVE(store = BuildNamedGeneric( |
| 5075 STORE, literal, name, value)); |
5075 } else { | 5076 } else { |
5076 PropertyAccessInfo info(this, STORE, ToType(map), name); | 5077 PropertyAccessInfo info(this, STORE, ToType(map), name); |
5077 if (info.CanAccessMonomorphic()) { | 5078 if (info.CanAccessMonomorphic()) { |
5078 HValue* checked_literal = BuildCheckMap(literal, map); | 5079 HValue* checked_literal = BuildCheckMap(literal, map); |
5079 ASSERT(!info.lookup()->IsPropertyCallbacks()); | 5080 ASSERT(!info.lookup()->IsPropertyCallbacks()); |
5080 store = BuildMonomorphicAccess( | 5081 store = BuildMonomorphicAccess( |
5081 &info, literal, checked_literal, value, | 5082 &info, literal, checked_literal, value, |
5082 BailoutId::None(), BailoutId::None()); | 5083 BailoutId::None(), BailoutId::None()); |
5083 } else { | 5084 } else { |
5084 CHECK_ALIVE( | 5085 CHECK_ALIVE(store = BuildNamedGeneric( |
5085 store = BuildStoreNamedGeneric(literal, name, value)); | 5086 STORE, literal, name, value)); |
5086 } | 5087 } |
5087 } | 5088 } |
5088 AddInstruction(store); | 5089 AddInstruction(store); |
5089 if (store->HasObservableSideEffects()) { | 5090 if (store->HasObservableSideEffects()) { |
5090 Add<HSimulate>(key->id(), REMOVABLE_SIMULATE); | 5091 Add<HSimulate>(key->id(), REMOVABLE_SIMULATE); |
5091 } | 5092 } |
5092 } else { | 5093 } else { |
5093 CHECK_ALIVE(VisitForEffect(value)); | 5094 CHECK_ALIVE(VisitForEffect(value)); |
5094 } | 5095 } |
5095 break; | 5096 break; |
(...skipping 211 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5307 | 5308 |
5308 if (transition_to_field) { | 5309 if (transition_to_field) { |
5309 HConstant* transition_constant = Add<HConstant>(info->transition()); | 5310 HConstant* transition_constant = Add<HConstant>(info->transition()); |
5310 instr->SetTransition(transition_constant, top_info()); | 5311 instr->SetTransition(transition_constant, top_info()); |
5311 instr->SetGVNFlag(kChangesMaps); | 5312 instr->SetGVNFlag(kChangesMaps); |
5312 } | 5313 } |
5313 return instr; | 5314 return instr; |
5314 } | 5315 } |
5315 | 5316 |
5316 | 5317 |
5317 HInstruction* HOptimizedGraphBuilder::BuildStoreNamedGeneric( | |
5318 HValue* object, | |
5319 Handle<String> name, | |
5320 HValue* value, | |
5321 bool is_uninitialized) { | |
5322 if (is_uninitialized) { | |
5323 Add<HDeoptimize>("Insufficient type feedback for property assignment", | |
5324 Deoptimizer::SOFT); | |
5325 } | |
5326 | |
5327 return New<HStoreNamedGeneric>( | |
5328 object, | |
5329 name, | |
5330 value, | |
5331 function_strict_mode_flag()); | |
5332 } | |
5333 | |
5334 | |
5335 bool HOptimizedGraphBuilder::PropertyAccessInfo::IsCompatible( | 5318 bool HOptimizedGraphBuilder::PropertyAccessInfo::IsCompatible( |
5336 PropertyAccessInfo* info) { | 5319 PropertyAccessInfo* info) { |
5337 if (!CanInlinePropertyAccess(type_)) return false; | 5320 if (!CanInlinePropertyAccess(type_)) return false; |
5338 | 5321 |
5339 // Currently only handle Type::Number as a polymorphic case. | 5322 // Currently only handle Type::Number as a polymorphic case. |
5340 // TODO(verwaest): Support monomorphic handling of numbers with a HCheckNumber | 5323 // TODO(verwaest): Support monomorphic handling of numbers with a HCheckNumber |
5341 // instruction. | 5324 // instruction. |
5342 if (type_->Is(Type::Number())) return false; | 5325 if (type_->Is(Type::Number())) return false; |
5343 | 5326 |
5344 // Values are only compatible for monomorphic load if they all behave the same | 5327 // Values are only compatible for monomorphic load if they all behave the same |
(...skipping 369 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5714 } | 5697 } |
5715 | 5698 |
5716 // Finish up. Unconditionally deoptimize if we've handled all the maps we | 5699 // Finish up. Unconditionally deoptimize if we've handled all the maps we |
5717 // know about and do not want to handle ones we've never seen. Otherwise | 5700 // know about and do not want to handle ones we've never seen. Otherwise |
5718 // use a generic IC. | 5701 // use a generic IC. |
5719 if (count == types->length() && FLAG_deoptimize_uncommon_cases) { | 5702 if (count == types->length() && FLAG_deoptimize_uncommon_cases) { |
5720 // Because the deopt may be the only path in the polymorphic load, make sure | 5703 // Because the deopt may be the only path in the polymorphic load, make sure |
5721 // that the environment stack matches the depth on deopt that it otherwise | 5704 // that the environment stack matches the depth on deopt that it otherwise |
5722 // would have had after a successful load. | 5705 // would have had after a successful load. |
5723 if (!ast_context()->IsEffect()) Push(graph()->GetConstant0()); | 5706 if (!ast_context()->IsEffect()) Push(graph()->GetConstant0()); |
5724 const char* message = ""; | 5707 FinishExitWithHardDeoptimization("Uknown map in polymorphic access", join); |
5725 switch (access_type) { | |
5726 case LOAD: | |
5727 message = "Unknown map in polymorphic load"; | |
5728 break; | |
5729 case STORE: | |
5730 message = "Unknown map in polymorphic store"; | |
5731 break; | |
5732 } | |
5733 FinishExitWithHardDeoptimization(message, join); | |
5734 } else { | 5708 } else { |
5735 HValue* result = NULL; | 5709 HInstruction* instr = BuildNamedGeneric(access_type, object, name, value); |
5736 switch (access_type) { | 5710 AddInstruction(instr); |
5737 case LOAD: | 5711 if (!ast_context()->IsEffect()) Push(access_type == LOAD ? instr : value); |
5738 result = Add<HLoadNamedGeneric>(object, name); | |
5739 break; | |
5740 case STORE: | |
5741 AddInstruction(BuildStoreNamedGeneric(object, name, value)); | |
5742 result = value; | |
5743 break; | |
5744 } | |
5745 if (!ast_context()->IsEffect()) Push(result); | |
5746 | 5712 |
5747 if (join != NULL) { | 5713 if (join != NULL) { |
5748 Goto(join); | 5714 Goto(join); |
5749 } else { | 5715 } else { |
5750 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); | 5716 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); |
5751 if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop()); | 5717 if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop()); |
5752 return; | 5718 return; |
5753 } | 5719 } |
5754 } | 5720 } |
5755 | 5721 |
(...skipping 431 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6187 if (string->IsConstant()) { | 6153 if (string->IsConstant()) { |
6188 HConstant* c_string = HConstant::cast(string); | 6154 HConstant* c_string = HConstant::cast(string); |
6189 if (c_string->HasStringValue()) { | 6155 if (c_string->HasStringValue()) { |
6190 return Add<HConstant>(c_string->StringValue()->length()); | 6156 return Add<HConstant>(c_string->StringValue()->length()); |
6191 } | 6157 } |
6192 } | 6158 } |
6193 return AddLoadNamedField(string, HObjectAccess::ForStringLength()); | 6159 return AddLoadNamedField(string, HObjectAccess::ForStringLength()); |
6194 } | 6160 } |
6195 | 6161 |
6196 | 6162 |
6197 HInstruction* HOptimizedGraphBuilder::BuildLoadNamedGeneric( | 6163 HInstruction* HOptimizedGraphBuilder::BuildNamedGeneric( |
| 6164 PropertyAccessType access_type, |
6198 HValue* object, | 6165 HValue* object, |
6199 Handle<String> name, | 6166 Handle<String> name, |
| 6167 HValue* value, |
6200 bool is_uninitialized) { | 6168 bool is_uninitialized) { |
6201 if (is_uninitialized) { | 6169 if (is_uninitialized) { |
6202 Add<HDeoptimize>("Insufficient type feedback for generic named load", | 6170 Add<HDeoptimize>("Insufficient type feedback for generic named access", |
6203 Deoptimizer::SOFT); | 6171 Deoptimizer::SOFT); |
6204 } | 6172 } |
6205 return New<HLoadNamedGeneric>(object, name); | 6173 if (access_type == LOAD) { |
| 6174 return New<HLoadNamedGeneric>(object, name); |
| 6175 } else { |
| 6176 return New<HStoreNamedGeneric>( |
| 6177 object, name, value, function_strict_mode_flag()); |
| 6178 } |
6206 } | 6179 } |
6207 | 6180 |
6208 | 6181 |
6209 | 6182 |
6210 HInstruction* HOptimizedGraphBuilder::BuildLoadKeyedGeneric(HValue* object, | 6183 HInstruction* HOptimizedGraphBuilder::BuildLoadKeyedGeneric(HValue* object, |
6211 HValue* key) { | 6184 HValue* key) { |
6212 return New<HLoadKeyedGeneric>(object, key); | 6185 return New<HLoadKeyedGeneric>(object, key); |
6213 } | 6186 } |
6214 | 6187 |
6215 | 6188 |
(...skipping 425 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6641 if (AreStringTypes(types)) { | 6614 if (AreStringTypes(types)) { |
6642 checked_object = | 6615 checked_object = |
6643 Add<HCheckInstanceType>(object, HCheckInstanceType::IS_STRING); | 6616 Add<HCheckInstanceType>(object, HCheckInstanceType::IS_STRING); |
6644 } else { | 6617 } else { |
6645 checked_object = Add<HCheckMaps>(object, types); | 6618 checked_object = Add<HCheckMaps>(object, types); |
6646 } | 6619 } |
6647 return BuildMonomorphicAccess( | 6620 return BuildMonomorphicAccess( |
6648 &info, object, checked_object, value, ast_id, return_id); | 6621 &info, object, checked_object, value, ast_id, return_id); |
6649 } | 6622 } |
6650 | 6623 |
6651 if (access == LOAD) { | 6624 return BuildNamedGeneric(access, object, name, value, is_uninitialized); |
6652 return BuildLoadNamedGeneric(object, name, is_uninitialized); | |
6653 } else { | |
6654 return BuildStoreNamedGeneric(object, name, value, is_uninitialized); | |
6655 } | |
6656 } | 6625 } |
6657 | 6626 |
6658 | 6627 |
6659 void HOptimizedGraphBuilder::PushLoad(Property* expr, | 6628 void HOptimizedGraphBuilder::PushLoad(Property* expr, |
6660 HValue* object, | 6629 HValue* object, |
6661 HValue* key) { | 6630 HValue* key) { |
6662 ValueContext for_value(this, ARGUMENTS_NOT_ALLOWED); | 6631 ValueContext for_value(this, ARGUMENTS_NOT_ALLOWED); |
6663 Push(object); | 6632 Push(object); |
6664 if (key != NULL) Push(key); | 6633 if (key != NULL) Push(key); |
6665 BuildLoad(expr, expr->LoadId()); | 6634 BuildLoad(expr, expr->LoadId()); |
(...skipping 331 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6997 // use a generic IC. | 6966 // use a generic IC. |
6998 if (ordered_functions == types->length() && FLAG_deoptimize_uncommon_cases) { | 6967 if (ordered_functions == types->length() && FLAG_deoptimize_uncommon_cases) { |
6999 // Because the deopt may be the only path in the polymorphic call, make sure | 6968 // Because the deopt may be the only path in the polymorphic call, make sure |
7000 // that the environment stack matches the depth on deopt that it otherwise | 6969 // that the environment stack matches the depth on deopt that it otherwise |
7001 // would have had after a successful call. | 6970 // would have had after a successful call. |
7002 Drop(1); // Drop receiver. | 6971 Drop(1); // Drop receiver. |
7003 if (!ast_context()->IsEffect()) Push(graph()->GetConstant0()); | 6972 if (!ast_context()->IsEffect()) Push(graph()->GetConstant0()); |
7004 FinishExitWithHardDeoptimization("Unknown map in polymorphic call", join); | 6973 FinishExitWithHardDeoptimization("Unknown map in polymorphic call", join); |
7005 } else { | 6974 } else { |
7006 Property* prop = expr->expression()->AsProperty(); | 6975 Property* prop = expr->expression()->AsProperty(); |
7007 HInstruction* function = BuildLoadNamedGeneric( | 6976 HInstruction* function = BuildNamedGeneric( |
7008 receiver, name, prop->IsUninitialized()); | 6977 LOAD, receiver, name, NULL, prop->IsUninitialized()); |
7009 AddInstruction(function); | 6978 AddInstruction(function); |
7010 Push(function); | 6979 Push(function); |
7011 AddSimulate(prop->LoadId(), REMOVABLE_SIMULATE); | 6980 AddSimulate(prop->LoadId(), REMOVABLE_SIMULATE); |
7012 | 6981 |
7013 environment()->SetExpressionStackAt(1, function); | 6982 environment()->SetExpressionStackAt(1, function); |
7014 environment()->SetExpressionStackAt(0, receiver); | 6983 environment()->SetExpressionStackAt(0, receiver); |
7015 CHECK_ALIVE(VisitExpressions(expr->arguments())); | 6984 CHECK_ALIVE(VisitExpressions(expr->arguments())); |
7016 | 6985 |
7017 CallFunctionFlags flags = receiver->type().IsJSObject() | 6986 CallFunctionFlags flags = receiver->type().IsJSObject() |
7018 ? NO_CALL_FUNCTION_FLAGS : CALL_AS_METHOD; | 6987 ? NO_CALL_FUNCTION_FLAGS : CALL_AS_METHOD; |
(...skipping 4224 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
11243 if (ShouldProduceTraceOutput()) { | 11212 if (ShouldProduceTraceOutput()) { |
11244 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); | 11213 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); |
11245 } | 11214 } |
11246 | 11215 |
11247 #ifdef DEBUG | 11216 #ifdef DEBUG |
11248 graph_->Verify(false); // No full verify. | 11217 graph_->Verify(false); // No full verify. |
11249 #endif | 11218 #endif |
11250 } | 11219 } |
11251 | 11220 |
11252 } } // namespace v8::internal | 11221 } } // namespace v8::internal |
OLD | NEW |