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