OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/crankshaft/hydrogen.h" | 5 #include "src/crankshaft/hydrogen.h" |
6 | 6 |
7 #include <sstream> | 7 #include <sstream> |
8 | 8 |
9 #include "src/allocation-site-scopes.h" | 9 #include "src/allocation-site-scopes.h" |
10 #include "src/ast/ast-numbering.h" | 10 #include "src/ast/ast-numbering.h" |
(...skipping 1088 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1099 void HGraphBuilder::IfBuilder::Else() { | 1099 void HGraphBuilder::IfBuilder::Else() { |
1100 DCHECK(did_then_); | 1100 DCHECK(did_then_); |
1101 DCHECK(!captured_); | 1101 DCHECK(!captured_); |
1102 DCHECK(!finished_); | 1102 DCHECK(!finished_); |
1103 AddMergeAtJoinBlock(false); | 1103 AddMergeAtJoinBlock(false); |
1104 builder()->set_current_block(first_false_block_); | 1104 builder()->set_current_block(first_false_block_); |
1105 pending_merge_block_ = true; | 1105 pending_merge_block_ = true; |
1106 did_else_ = true; | 1106 did_else_ = true; |
1107 } | 1107 } |
1108 | 1108 |
1109 | 1109 void HGraphBuilder::IfBuilder::Deopt(DeoptimizeReason reason) { |
1110 void HGraphBuilder::IfBuilder::Deopt(Deoptimizer::DeoptReason reason) { | |
1111 DCHECK(did_then_); | 1110 DCHECK(did_then_); |
1112 builder()->Add<HDeoptimize>(reason, Deoptimizer::EAGER); | 1111 builder()->Add<HDeoptimize>(reason, Deoptimizer::EAGER); |
1113 AddMergeAtJoinBlock(true); | 1112 AddMergeAtJoinBlock(true); |
1114 } | 1113 } |
1115 | 1114 |
1116 | 1115 |
1117 void HGraphBuilder::IfBuilder::Return(HValue* value) { | 1116 void HGraphBuilder::IfBuilder::Return(HValue* value) { |
1118 HValue* parameter_count = builder()->graph()->GetConstantMinus1(); | 1117 HValue* parameter_count = builder()->graph()->GetConstantMinus1(); |
1119 builder()->FinishExitCurrentBlock( | 1118 builder()->FinishExitCurrentBlock( |
1120 builder()->New<HReturn>(value, parameter_count)); | 1119 builder()->New<HReturn>(value, parameter_count)); |
(...skipping 385 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1506 Add<HLoadNamedField>(map, nullptr, HObjectAccess::ForMapBitField3()); | 1505 Add<HLoadNamedField>(map, nullptr, HObjectAccess::ForMapBitField3()); |
1507 return BuildDecodeField<Map::EnumLengthBits>(bit_field3); | 1506 return BuildDecodeField<Map::EnumLengthBits>(bit_field3); |
1508 } | 1507 } |
1509 | 1508 |
1510 | 1509 |
1511 HValue* HGraphBuilder::BuildCheckHeapObject(HValue* obj) { | 1510 HValue* HGraphBuilder::BuildCheckHeapObject(HValue* obj) { |
1512 if (obj->type().IsHeapObject()) return obj; | 1511 if (obj->type().IsHeapObject()) return obj; |
1513 return Add<HCheckHeapObject>(obj); | 1512 return Add<HCheckHeapObject>(obj); |
1514 } | 1513 } |
1515 | 1514 |
1516 | 1515 void HGraphBuilder::FinishExitWithHardDeoptimization(DeoptimizeReason reason) { |
1517 void HGraphBuilder::FinishExitWithHardDeoptimization( | |
1518 Deoptimizer::DeoptReason reason) { | |
1519 Add<HDeoptimize>(reason, Deoptimizer::EAGER); | 1516 Add<HDeoptimize>(reason, Deoptimizer::EAGER); |
1520 FinishExitCurrentBlock(New<HAbnormalExit>()); | 1517 FinishExitCurrentBlock(New<HAbnormalExit>()); |
1521 } | 1518 } |
1522 | 1519 |
1523 | 1520 |
1524 HValue* HGraphBuilder::BuildCheckString(HValue* string) { | 1521 HValue* HGraphBuilder::BuildCheckString(HValue* string) { |
1525 if (!string->type().IsString()) { | 1522 if (!string->type().IsString()) { |
1526 DCHECK(!string->IsConstant() || | 1523 DCHECK(!string->IsConstant() || |
1527 !HConstant::cast(string)->HasStringValue()); | 1524 !HConstant::cast(string)->HasStringValue()); |
1528 BuildCheckHeapObject(string); | 1525 BuildCheckHeapObject(string); |
(...skipping 297 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1826 // not one of the global object types. | 1823 // not one of the global object types. |
1827 HValue* map = | 1824 HValue* map = |
1828 Add<HLoadNamedField>(receiver, nullptr, HObjectAccess::ForMap()); | 1825 Add<HLoadNamedField>(receiver, nullptr, HObjectAccess::ForMap()); |
1829 HValue* instance_type = | 1826 HValue* instance_type = |
1830 Add<HLoadNamedField>(map, nullptr, HObjectAccess::ForMapInstanceType()); | 1827 Add<HLoadNamedField>(map, nullptr, HObjectAccess::ForMapInstanceType()); |
1831 HValue* global_type = Add<HConstant>(JS_GLOBAL_OBJECT_TYPE); | 1828 HValue* global_type = Add<HConstant>(JS_GLOBAL_OBJECT_TYPE); |
1832 | 1829 |
1833 IfBuilder if_global_object(this); | 1830 IfBuilder if_global_object(this); |
1834 if_global_object.If<HCompareNumericAndBranch>(instance_type, global_type, | 1831 if_global_object.If<HCompareNumericAndBranch>(instance_type, global_type, |
1835 Token::EQ); | 1832 Token::EQ); |
1836 if_global_object.ThenDeopt(Deoptimizer::kReceiverWasAGlobalObject); | 1833 if_global_object.ThenDeopt(DeoptimizeReason::kReceiverWasAGlobalObject); |
1837 if_global_object.End(); | 1834 if_global_object.End(); |
1838 } | 1835 } |
1839 | 1836 |
1840 | 1837 |
1841 void HGraphBuilder::BuildTestForDictionaryProperties( | 1838 void HGraphBuilder::BuildTestForDictionaryProperties( |
1842 HValue* object, | 1839 HValue* object, |
1843 HIfContinuation* continuation) { | 1840 HIfContinuation* continuation) { |
1844 HValue* properties = Add<HLoadNamedField>( | 1841 HValue* properties = Add<HLoadNamedField>( |
1845 object, nullptr, HObjectAccess::ForPropertiesPointer()); | 1842 object, nullptr, HObjectAccess::ForPropertiesPointer()); |
1846 HValue* properties_map = | 1843 HValue* properties_map = |
(...skipping 329 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2176 if_objectiskey.Then(); | 2173 if_objectiskey.Then(); |
2177 { | 2174 { |
2178 // Make the key_index available. | 2175 // Make the key_index available. |
2179 Push(key_index); | 2176 Push(key_index); |
2180 } | 2177 } |
2181 if_objectiskey.JoinContinuation(&found); | 2178 if_objectiskey.JoinContinuation(&found); |
2182 } | 2179 } |
2183 if_objectissmi.Else(); | 2180 if_objectissmi.Else(); |
2184 { | 2181 { |
2185 if (type->Is(Type::SignedSmall())) { | 2182 if (type->Is(Type::SignedSmall())) { |
2186 if_objectissmi.Deopt(Deoptimizer::kExpectedSmi); | 2183 if_objectissmi.Deopt(DeoptimizeReason::kExpectedSmi); |
2187 } else { | 2184 } else { |
2188 // Check if the object is a heap number. | 2185 // Check if the object is a heap number. |
2189 IfBuilder if_objectisnumber(this); | 2186 IfBuilder if_objectisnumber(this); |
2190 HValue* objectisnumber = if_objectisnumber.If<HCompareMap>( | 2187 HValue* objectisnumber = if_objectisnumber.If<HCompareMap>( |
2191 object, isolate()->factory()->heap_number_map()); | 2188 object, isolate()->factory()->heap_number_map()); |
2192 if_objectisnumber.Then(); | 2189 if_objectisnumber.Then(); |
2193 { | 2190 { |
2194 // Compute hash for heap number similar to double_get_hash(). | 2191 // Compute hash for heap number similar to double_get_hash(). |
2195 HValue* low = Add<HLoadNamedField>( | 2192 HValue* low = Add<HLoadNamedField>( |
2196 object, objectisnumber, | 2193 object, objectisnumber, |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2232 } | 2229 } |
2233 if_keyeqobject.JoinContinuation(&found); | 2230 if_keyeqobject.JoinContinuation(&found); |
2234 } | 2231 } |
2235 if_keyisheapnumber.JoinContinuation(&found); | 2232 if_keyisheapnumber.JoinContinuation(&found); |
2236 } | 2233 } |
2237 if_keyisnotsmi.JoinContinuation(&found); | 2234 if_keyisnotsmi.JoinContinuation(&found); |
2238 } | 2235 } |
2239 if_objectisnumber.Else(); | 2236 if_objectisnumber.Else(); |
2240 { | 2237 { |
2241 if (type->Is(Type::Number())) { | 2238 if (type->Is(Type::Number())) { |
2242 if_objectisnumber.Deopt(Deoptimizer::kExpectedHeapNumber); | 2239 if_objectisnumber.Deopt(DeoptimizeReason::kExpectedHeapNumber); |
2243 } | 2240 } |
2244 } | 2241 } |
2245 if_objectisnumber.JoinContinuation(&found); | 2242 if_objectisnumber.JoinContinuation(&found); |
2246 } | 2243 } |
2247 } | 2244 } |
2248 if_objectissmi.JoinContinuation(&found); | 2245 if_objectissmi.JoinContinuation(&found); |
2249 | 2246 |
2250 // Check for cache hit. | 2247 // Check for cache hit. |
2251 IfBuilder if_found(this, &found); | 2248 IfBuilder if_found(this, &found); |
2252 if_found.Then(); | 2249 if_found.Then(); |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2325 receiver_map, nullptr, | 2322 receiver_map, nullptr, |
2326 HObjectAccess::ForMapInObjectPropertiesOrConstructorFunctionIndex()); | 2323 HObjectAccess::ForMapInObjectPropertiesOrConstructorFunctionIndex()); |
2327 | 2324 |
2328 // Check if {receiver} has a constructor (null and undefined have no | 2325 // Check if {receiver} has a constructor (null and undefined have no |
2329 // constructors, so we deoptimize to the runtime to throw an exception). | 2326 // constructors, so we deoptimize to the runtime to throw an exception). |
2330 IfBuilder constructor_function_index_is_invalid(this); | 2327 IfBuilder constructor_function_index_is_invalid(this); |
2331 constructor_function_index_is_invalid.If<HCompareNumericAndBranch>( | 2328 constructor_function_index_is_invalid.If<HCompareNumericAndBranch>( |
2332 constructor_function_index, | 2329 constructor_function_index, |
2333 Add<HConstant>(Map::kNoConstructorFunctionIndex), Token::EQ); | 2330 Add<HConstant>(Map::kNoConstructorFunctionIndex), Token::EQ); |
2334 constructor_function_index_is_invalid.ThenDeopt( | 2331 constructor_function_index_is_invalid.ThenDeopt( |
2335 Deoptimizer::kUndefinedOrNullInToObject); | 2332 DeoptimizeReason::kUndefinedOrNullInToObject); |
2336 constructor_function_index_is_invalid.End(); | 2333 constructor_function_index_is_invalid.End(); |
2337 | 2334 |
2338 // Use the global constructor function. | 2335 // Use the global constructor function. |
2339 Push(constructor_function_index); | 2336 Push(constructor_function_index); |
2340 } | 2337 } |
2341 receiver_is_not_spec_object.JoinContinuation(&wrap); | 2338 receiver_is_not_spec_object.JoinContinuation(&wrap); |
2342 } | 2339 } |
2343 receiver_is_smi.JoinContinuation(&wrap); | 2340 receiver_is_smi.JoinContinuation(&wrap); |
2344 | 2341 |
2345 // Wrap the receiver if necessary. | 2342 // Wrap the receiver if necessary. |
(...skipping 487 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2833 IfBuilder length_checker(this); | 2830 IfBuilder length_checker(this); |
2834 length_checker.If<HCompareNumericAndBranch>(key, length, Token::LT); | 2831 length_checker.If<HCompareNumericAndBranch>(key, length, Token::LT); |
2835 length_checker.Then(); | 2832 length_checker.Then(); |
2836 IfBuilder negative_checker(this); | 2833 IfBuilder negative_checker(this); |
2837 HValue* bounds_check = negative_checker.If<HCompareNumericAndBranch>( | 2834 HValue* bounds_check = negative_checker.If<HCompareNumericAndBranch>( |
2838 key, graph()->GetConstant0(), Token::GTE); | 2835 key, graph()->GetConstant0(), Token::GTE); |
2839 negative_checker.Then(); | 2836 negative_checker.Then(); |
2840 HInstruction* result = AddElementAccess( | 2837 HInstruction* result = AddElementAccess( |
2841 backing_store, key, val, bounds_check, checked_object->ActualValue(), | 2838 backing_store, key, val, bounds_check, checked_object->ActualValue(), |
2842 elements_kind, access_type); | 2839 elements_kind, access_type); |
2843 negative_checker.ElseDeopt(Deoptimizer::kNegativeKeyEncountered); | 2840 negative_checker.ElseDeopt(DeoptimizeReason::kNegativeKeyEncountered); |
2844 negative_checker.End(); | 2841 negative_checker.End(); |
2845 length_checker.End(); | 2842 length_checker.End(); |
2846 return result; | 2843 return result; |
2847 } else { | 2844 } else { |
2848 DCHECK(store_mode == STANDARD_STORE); | 2845 DCHECK(store_mode == STANDARD_STORE); |
2849 checked_key = Add<HBoundsCheck>(key, length); | 2846 checked_key = Add<HBoundsCheck>(key, length); |
2850 return AddElementAccess(backing_store, checked_key, val, checked_object, | 2847 return AddElementAccess(backing_store, checked_key, val, checked_object, |
2851 checked_object->ActualValue(), elements_kind, | 2848 checked_object->ActualValue(), elements_kind, |
2852 access_type); | 2849 access_type); |
2853 } | 2850 } |
(...skipping 2411 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5265 | 5262 |
5266 CHECK_ALIVE(VisitForValue(stmt->enumerable())); | 5263 CHECK_ALIVE(VisitForValue(stmt->enumerable())); |
5267 HValue* enumerable = Top(); // Leave enumerable at the top. | 5264 HValue* enumerable = Top(); // Leave enumerable at the top. |
5268 | 5265 |
5269 IfBuilder if_undefined_or_null(this); | 5266 IfBuilder if_undefined_or_null(this); |
5270 if_undefined_or_null.If<HCompareObjectEqAndBranch>( | 5267 if_undefined_or_null.If<HCompareObjectEqAndBranch>( |
5271 enumerable, graph()->GetConstantUndefined()); | 5268 enumerable, graph()->GetConstantUndefined()); |
5272 if_undefined_or_null.Or(); | 5269 if_undefined_or_null.Or(); |
5273 if_undefined_or_null.If<HCompareObjectEqAndBranch>( | 5270 if_undefined_or_null.If<HCompareObjectEqAndBranch>( |
5274 enumerable, graph()->GetConstantNull()); | 5271 enumerable, graph()->GetConstantNull()); |
5275 if_undefined_or_null.ThenDeopt(Deoptimizer::kUndefinedOrNullInForIn); | 5272 if_undefined_or_null.ThenDeopt(DeoptimizeReason::kUndefinedOrNullInForIn); |
5276 if_undefined_or_null.End(); | 5273 if_undefined_or_null.End(); |
5277 BuildForInBody(stmt, each_var, enumerable); | 5274 BuildForInBody(stmt, each_var, enumerable); |
5278 } | 5275 } |
5279 | 5276 |
5280 | 5277 |
5281 void HOptimizedGraphBuilder::BuildForInBody(ForInStatement* stmt, | 5278 void HOptimizedGraphBuilder::BuildForInBody(ForInStatement* stmt, |
5282 Variable* each_var, | 5279 Variable* each_var, |
5283 HValue* enumerable) { | 5280 HValue* enumerable) { |
5284 Handle<Map> meta_map = isolate()->factory()->meta_map(); | 5281 Handle<Map> meta_map = isolate()->factory()->meta_map(); |
5285 bool fast = stmt->for_in_type() == ForInStatement::FAST_FOR_IN; | 5282 bool fast = stmt->for_in_type() == ForInStatement::FAST_FOR_IN; |
(...skipping 1391 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6677 | 6674 |
6678 if (current_block() != NULL) Goto(join); | 6675 if (current_block() != NULL) Goto(join); |
6679 set_current_block(if_false); | 6676 set_current_block(if_false); |
6680 } | 6677 } |
6681 | 6678 |
6682 // Finish up. Unconditionally deoptimize if we've handled all the maps we | 6679 // Finish up. Unconditionally deoptimize if we've handled all the maps we |
6683 // know about and do not want to handle ones we've never seen. Otherwise | 6680 // know about and do not want to handle ones we've never seen. Otherwise |
6684 // use a generic IC. | 6681 // use a generic IC. |
6685 if (count == maps->length() && FLAG_deoptimize_uncommon_cases) { | 6682 if (count == maps->length() && FLAG_deoptimize_uncommon_cases) { |
6686 FinishExitWithHardDeoptimization( | 6683 FinishExitWithHardDeoptimization( |
6687 Deoptimizer::kUnknownMapInPolymorphicAccess); | 6684 DeoptimizeReason::kUnknownMapInPolymorphicAccess); |
6688 } else { | 6685 } else { |
6689 HInstruction* instr = | 6686 HInstruction* instr = |
6690 BuildNamedGeneric(access_type, expr, slot, object, name, value); | 6687 BuildNamedGeneric(access_type, expr, slot, object, name, value); |
6691 AddInstruction(instr); | 6688 AddInstruction(instr); |
6692 if (!ast_context()->IsEffect()) Push(access_type == LOAD ? instr : value); | 6689 if (!ast_context()->IsEffect()) Push(access_type == LOAD ? instr : value); |
6693 | 6690 |
6694 if (join != NULL) { | 6691 if (join != NULL) { |
6695 Goto(join); | 6692 Goto(join); |
6696 } else { | 6693 } else { |
6697 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); | 6694 Add<HSimulate>(ast_id, REMOVABLE_SIMULATE); |
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6863 if (type == kUseCell) { | 6860 if (type == kUseCell) { |
6864 Handle<PropertyCell> cell = it.GetPropertyCell(); | 6861 Handle<PropertyCell> cell = it.GetPropertyCell(); |
6865 top_info()->dependencies()->AssumePropertyCell(cell); | 6862 top_info()->dependencies()->AssumePropertyCell(cell); |
6866 auto cell_type = it.property_details().cell_type(); | 6863 auto cell_type = it.property_details().cell_type(); |
6867 if (cell_type == PropertyCellType::kConstant || | 6864 if (cell_type == PropertyCellType::kConstant || |
6868 cell_type == PropertyCellType::kUndefined) { | 6865 cell_type == PropertyCellType::kUndefined) { |
6869 Handle<Object> constant(cell->value(), isolate()); | 6866 Handle<Object> constant(cell->value(), isolate()); |
6870 if (value->IsConstant()) { | 6867 if (value->IsConstant()) { |
6871 HConstant* c_value = HConstant::cast(value); | 6868 HConstant* c_value = HConstant::cast(value); |
6872 if (!constant.is_identical_to(c_value->handle(isolate()))) { | 6869 if (!constant.is_identical_to(c_value->handle(isolate()))) { |
6873 Add<HDeoptimize>(Deoptimizer::kConstantGlobalVariableAssignment, | 6870 Add<HDeoptimize>(DeoptimizeReason::kConstantGlobalVariableAssignment, |
6874 Deoptimizer::EAGER); | 6871 Deoptimizer::EAGER); |
6875 } | 6872 } |
6876 } else { | 6873 } else { |
6877 HValue* c_constant = Add<HConstant>(constant); | 6874 HValue* c_constant = Add<HConstant>(constant); |
6878 IfBuilder builder(this); | 6875 IfBuilder builder(this); |
6879 if (constant->IsNumber()) { | 6876 if (constant->IsNumber()) { |
6880 builder.If<HCompareNumericAndBranch>(value, c_constant, Token::EQ); | 6877 builder.If<HCompareNumericAndBranch>(value, c_constant, Token::EQ); |
6881 } else { | 6878 } else { |
6882 builder.If<HCompareObjectEqAndBranch>(value, c_constant); | 6879 builder.If<HCompareObjectEqAndBranch>(value, c_constant); |
6883 } | 6880 } |
6884 builder.Then(); | 6881 builder.Then(); |
6885 builder.Else(); | 6882 builder.Else(); |
6886 Add<HDeoptimize>(Deoptimizer::kConstantGlobalVariableAssignment, | 6883 Add<HDeoptimize>(DeoptimizeReason::kConstantGlobalVariableAssignment, |
6887 Deoptimizer::EAGER); | 6884 Deoptimizer::EAGER); |
6888 builder.End(); | 6885 builder.End(); |
6889 } | 6886 } |
6890 } | 6887 } |
6891 HConstant* cell_constant = Add<HConstant>(cell); | 6888 HConstant* cell_constant = Add<HConstant>(cell); |
6892 auto access = HObjectAccess::ForPropertyCellValue(); | 6889 auto access = HObjectAccess::ForPropertyCellValue(); |
6893 if (cell_type == PropertyCellType::kConstantType) { | 6890 if (cell_type == PropertyCellType::kConstantType) { |
6894 switch (cell->GetConstantType()) { | 6891 switch (cell->GetConstantType()) { |
6895 case PropertyCellConstantType::kSmi: | 6892 case PropertyCellConstantType::kSmi: |
6896 access = access.WithRepresentation(Representation::Smi()); | 6893 access = access.WithRepresentation(Representation::Smi()); |
(...skipping 328 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7225 return New<HLoadNamedField>(string, nullptr, | 7222 return New<HLoadNamedField>(string, nullptr, |
7226 HObjectAccess::ForStringLength()); | 7223 HObjectAccess::ForStringLength()); |
7227 } | 7224 } |
7228 | 7225 |
7229 | 7226 |
7230 HInstruction* HOptimizedGraphBuilder::BuildNamedGeneric( | 7227 HInstruction* HOptimizedGraphBuilder::BuildNamedGeneric( |
7231 PropertyAccessType access_type, Expression* expr, FeedbackVectorSlot slot, | 7228 PropertyAccessType access_type, Expression* expr, FeedbackVectorSlot slot, |
7232 HValue* object, Handle<Name> name, HValue* value, bool is_uninitialized) { | 7229 HValue* object, Handle<Name> name, HValue* value, bool is_uninitialized) { |
7233 if (is_uninitialized) { | 7230 if (is_uninitialized) { |
7234 Add<HDeoptimize>( | 7231 Add<HDeoptimize>( |
7235 Deoptimizer::kInsufficientTypeFeedbackForGenericNamedAccess, | 7232 DeoptimizeReason::kInsufficientTypeFeedbackForGenericNamedAccess, |
7236 Deoptimizer::SOFT); | 7233 Deoptimizer::SOFT); |
7237 } | 7234 } |
7238 if (access_type == LOAD) { | 7235 if (access_type == LOAD) { |
7239 Handle<TypeFeedbackVector> vector = | 7236 Handle<TypeFeedbackVector> vector = |
7240 handle(current_feedback_vector(), isolate()); | 7237 handle(current_feedback_vector(), isolate()); |
7241 | 7238 |
7242 if (!expr->AsProperty()->key()->IsPropertyName()) { | 7239 if (!expr->AsProperty()->key()->IsPropertyName()) { |
7243 // It's possible that a keyed load of a constant string was converted | 7240 // It's possible that a keyed load of a constant string was converted |
7244 // to a named load. Here, at the last minute, we need to make sure to | 7241 // to a named load. Here, at the last minute, we need to make sure to |
7245 // use a generic Keyed Load if we are using the type vector, because | 7242 // use a generic Keyed Load if we are using the type vector, because |
(...skipping 337 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7583 } | 7580 } |
7584 | 7581 |
7585 // Ensure that we visited at least one map above that goes to join. This is | 7582 // Ensure that we visited at least one map above that goes to join. This is |
7586 // necessary because FinishExitWithHardDeoptimization does an AbnormalExit | 7583 // necessary because FinishExitWithHardDeoptimization does an AbnormalExit |
7587 // rather than joining the join block. If this becomes an issue, insert a | 7584 // rather than joining the join block. If this becomes an issue, insert a |
7588 // generic access in the case length() == 0. | 7585 // generic access in the case length() == 0. |
7589 DCHECK(join->predecessors()->length() > 0); | 7586 DCHECK(join->predecessors()->length() > 0); |
7590 // Deopt if none of the cases matched. | 7587 // Deopt if none of the cases matched. |
7591 NoObservableSideEffectsScope scope(this); | 7588 NoObservableSideEffectsScope scope(this); |
7592 FinishExitWithHardDeoptimization( | 7589 FinishExitWithHardDeoptimization( |
7593 Deoptimizer::kUnknownMapInPolymorphicElementAccess); | 7590 DeoptimizeReason::kUnknownMapInPolymorphicElementAccess); |
7594 set_current_block(join); | 7591 set_current_block(join); |
7595 return access_type == STORE ? val : Pop(); | 7592 return access_type == STORE ? val : Pop(); |
7596 } | 7593 } |
7597 | 7594 |
7598 HValue* HOptimizedGraphBuilder::HandleKeyedElementAccess( | 7595 HValue* HOptimizedGraphBuilder::HandleKeyedElementAccess( |
7599 HValue* obj, HValue* key, HValue* val, Expression* expr, | 7596 HValue* obj, HValue* key, HValue* val, Expression* expr, |
7600 FeedbackVectorSlot slot, BailoutId ast_id, BailoutId return_id, | 7597 FeedbackVectorSlot slot, BailoutId ast_id, BailoutId return_id, |
7601 PropertyAccessType access_type, bool* has_side_effects) { | 7598 PropertyAccessType access_type, bool* has_side_effects) { |
7602 // A keyed name access with type feedback may contain the name. | 7599 // A keyed name access with type feedback may contain the name. |
7603 Handle<TypeFeedbackVector> vector = | 7600 Handle<TypeFeedbackVector> vector = |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7700 obj, key, val, NULL, map, access_type, expr->GetStoreMode()); | 7697 obj, key, val, NULL, map, access_type, expr->GetStoreMode()); |
7701 } | 7698 } |
7702 } else if (!force_generic && (maps != NULL && !maps->is_empty())) { | 7699 } else if (!force_generic && (maps != NULL && !maps->is_empty())) { |
7703 return HandlePolymorphicElementAccess(expr, slot, obj, key, val, maps, | 7700 return HandlePolymorphicElementAccess(expr, slot, obj, key, val, maps, |
7704 access_type, expr->GetStoreMode(), | 7701 access_type, expr->GetStoreMode(), |
7705 has_side_effects); | 7702 has_side_effects); |
7706 } else { | 7703 } else { |
7707 if (access_type == STORE) { | 7704 if (access_type == STORE) { |
7708 if (expr->IsAssignment() && | 7705 if (expr->IsAssignment() && |
7709 expr->AsAssignment()->HasNoTypeInformation()) { | 7706 expr->AsAssignment()->HasNoTypeInformation()) { |
7710 Add<HDeoptimize>(Deoptimizer::kInsufficientTypeFeedbackForKeyedStore, | 7707 Add<HDeoptimize>( |
7711 Deoptimizer::SOFT); | 7708 DeoptimizeReason::kInsufficientTypeFeedbackForGenericKeyedAccess, |
| 7709 Deoptimizer::SOFT); |
7712 } | 7710 } |
7713 } else { | 7711 } else { |
7714 if (expr->AsProperty()->HasNoTypeInformation()) { | 7712 if (expr->AsProperty()->HasNoTypeInformation()) { |
7715 Add<HDeoptimize>(Deoptimizer::kInsufficientTypeFeedbackForKeyedLoad, | 7713 Add<HDeoptimize>( |
7716 Deoptimizer::SOFT); | 7714 DeoptimizeReason::kInsufficientTypeFeedbackForGenericKeyedAccess, |
| 7715 Deoptimizer::SOFT); |
7717 } | 7716 } |
7718 } | 7717 } |
7719 instr = AddInstruction( | 7718 instr = AddInstruction( |
7720 BuildKeyedGeneric(access_type, expr, slot, obj, key, val)); | 7719 BuildKeyedGeneric(access_type, expr, slot, obj, key, val)); |
7721 } | 7720 } |
7722 *has_side_effects = instr->HasObservableSideEffects(); | 7721 *has_side_effects = instr->HasObservableSideEffects(); |
7723 return instr; | 7722 return instr; |
7724 } | 7723 } |
7725 | 7724 |
7726 | 7725 |
(...skipping 456 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8183 } | 8182 } |
8184 | 8183 |
8185 if (current_block() != NULL) Goto(join); | 8184 if (current_block() != NULL) Goto(join); |
8186 set_current_block(if_false); | 8185 set_current_block(if_false); |
8187 } | 8186 } |
8188 | 8187 |
8189 // Finish up. Unconditionally deoptimize if we've handled all the maps we | 8188 // Finish up. Unconditionally deoptimize if we've handled all the maps we |
8190 // know about and do not want to handle ones we've never seen. Otherwise | 8189 // know about and do not want to handle ones we've never seen. Otherwise |
8191 // use a generic IC. | 8190 // use a generic IC. |
8192 if (ordered_functions == maps->length() && FLAG_deoptimize_uncommon_cases) { | 8191 if (ordered_functions == maps->length() && FLAG_deoptimize_uncommon_cases) { |
8193 FinishExitWithHardDeoptimization(Deoptimizer::kUnknownMapInPolymorphicCall); | 8192 FinishExitWithHardDeoptimization( |
| 8193 DeoptimizeReason::kUnknownMapInPolymorphicCall); |
8194 } else { | 8194 } else { |
8195 Property* prop = expr->expression()->AsProperty(); | 8195 Property* prop = expr->expression()->AsProperty(); |
8196 HInstruction* function = | 8196 HInstruction* function = |
8197 BuildNamedGeneric(LOAD, prop, prop->PropertyFeedbackSlot(), receiver, | 8197 BuildNamedGeneric(LOAD, prop, prop->PropertyFeedbackSlot(), receiver, |
8198 name, NULL, prop->IsUninitialized()); | 8198 name, NULL, prop->IsUninitialized()); |
8199 AddInstruction(function); | 8199 AddInstruction(function); |
8200 Push(function); | 8200 Push(function); |
8201 AddSimulate(prop->LoadId(), REMOVABLE_SIMULATE); | 8201 AddSimulate(prop->LoadId(), REMOVABLE_SIMULATE); |
8202 | 8202 |
8203 environment()->SetExpressionStackAt(1, function); | 8203 environment()->SetExpressionStackAt(1, function); |
(...skipping 1589 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9793 NewCallConstantFunction(known_function, argument_count, | 9793 NewCallConstantFunction(known_function, argument_count, |
9794 syntactic_tail_call_mode, tail_call_mode); | 9794 syntactic_tail_call_mode, tail_call_mode); |
9795 } | 9795 } |
9796 | 9796 |
9797 } else { | 9797 } else { |
9798 ArgumentsAllowedFlag arguments_flag = ARGUMENTS_NOT_ALLOWED; | 9798 ArgumentsAllowedFlag arguments_flag = ARGUMENTS_NOT_ALLOWED; |
9799 if (CanBeFunctionApplyArguments(expr) && expr->is_uninitialized()) { | 9799 if (CanBeFunctionApplyArguments(expr) && expr->is_uninitialized()) { |
9800 // We have to use EAGER deoptimization here because Deoptimizer::SOFT | 9800 // We have to use EAGER deoptimization here because Deoptimizer::SOFT |
9801 // gets ignored by the always-opt flag, which leads to incorrect code. | 9801 // gets ignored by the always-opt flag, which leads to incorrect code. |
9802 Add<HDeoptimize>( | 9802 Add<HDeoptimize>( |
9803 Deoptimizer::kInsufficientTypeFeedbackForCallWithArguments, | 9803 DeoptimizeReason::kInsufficientTypeFeedbackForCallWithArguments, |
9804 Deoptimizer::EAGER); | 9804 Deoptimizer::EAGER); |
9805 arguments_flag = ARGUMENTS_FAKED; | 9805 arguments_flag = ARGUMENTS_FAKED; |
9806 } | 9806 } |
9807 | 9807 |
9808 // Push the function under the receiver. | 9808 // Push the function under the receiver. |
9809 environment()->SetExpressionStackAt(0, function); | 9809 environment()->SetExpressionStackAt(0, function); |
9810 Push(receiver); | 9810 Push(receiver); |
9811 | 9811 |
9812 CHECK_ALIVE(VisitExpressions(expr->arguments(), arguments_flag)); | 9812 CHECK_ALIVE(VisitExpressions(expr->arguments(), arguments_flag)); |
9813 call = NewCallFunction(function, argument_count, syntactic_tail_call_mode, | 9813 call = NewCallFunction(function, argument_count, syntactic_tail_call_mode, |
(...skipping 1217 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
11031 left_type->Maybe(Type::Receiver()) || | 11031 left_type->Maybe(Type::Receiver()) || |
11032 right_type->Maybe(Type::String()) || | 11032 right_type->Maybe(Type::String()) || |
11033 right_type->Maybe(Type::Receiver())); | 11033 right_type->Maybe(Type::Receiver())); |
11034 } | 11034 } |
11035 | 11035 |
11036 Representation left_rep = RepresentationFor(left_type); | 11036 Representation left_rep = RepresentationFor(left_type); |
11037 Representation right_rep = RepresentationFor(right_type); | 11037 Representation right_rep = RepresentationFor(right_type); |
11038 | 11038 |
11039 if (!left_type->IsInhabited()) { | 11039 if (!left_type->IsInhabited()) { |
11040 Add<HDeoptimize>( | 11040 Add<HDeoptimize>( |
11041 Deoptimizer::kInsufficientTypeFeedbackForLHSOfBinaryOperation, | 11041 DeoptimizeReason::kInsufficientTypeFeedbackForLHSOfBinaryOperation, |
11042 Deoptimizer::SOFT); | 11042 Deoptimizer::SOFT); |
11043 left_type = Type::Any(); | 11043 left_type = Type::Any(); |
11044 left_rep = RepresentationFor(left_type); | 11044 left_rep = RepresentationFor(left_type); |
11045 maybe_string_add = op == Token::ADD; | 11045 maybe_string_add = op == Token::ADD; |
11046 } | 11046 } |
11047 | 11047 |
11048 if (!right_type->IsInhabited()) { | 11048 if (!right_type->IsInhabited()) { |
11049 Add<HDeoptimize>( | 11049 Add<HDeoptimize>( |
11050 Deoptimizer::kInsufficientTypeFeedbackForRHSOfBinaryOperation, | 11050 DeoptimizeReason::kInsufficientTypeFeedbackForRHSOfBinaryOperation, |
11051 Deoptimizer::SOFT); | 11051 Deoptimizer::SOFT); |
11052 right_type = Type::Any(); | 11052 right_type = Type::Any(); |
11053 right_rep = RepresentationFor(right_type); | 11053 right_rep = RepresentationFor(right_type); |
11054 maybe_string_add = op == Token::ADD; | 11054 maybe_string_add = op == Token::ADD; |
11055 } | 11055 } |
11056 | 11056 |
11057 if (!maybe_string_add) { | 11057 if (!maybe_string_add) { |
11058 left = TruncateToNumber(left, &left_type); | 11058 left = TruncateToNumber(left, &left_type); |
11059 right = TruncateToNumber(right, &right_type); | 11059 right = TruncateToNumber(right, &right_type); |
11060 } | 11060 } |
(...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
11224 instr = AddUncasted<HMul>(left, right); | 11224 instr = AddUncasted<HMul>(left, right); |
11225 break; | 11225 break; |
11226 case Token::MOD: { | 11226 case Token::MOD: { |
11227 if (fixed_right_arg.IsJust() && | 11227 if (fixed_right_arg.IsJust() && |
11228 !right->EqualsInteger32Constant(fixed_right_arg.FromJust())) { | 11228 !right->EqualsInteger32Constant(fixed_right_arg.FromJust())) { |
11229 HConstant* fixed_right = | 11229 HConstant* fixed_right = |
11230 Add<HConstant>(static_cast<int>(fixed_right_arg.FromJust())); | 11230 Add<HConstant>(static_cast<int>(fixed_right_arg.FromJust())); |
11231 IfBuilder if_same(this); | 11231 IfBuilder if_same(this); |
11232 if_same.If<HCompareNumericAndBranch>(right, fixed_right, Token::EQ); | 11232 if_same.If<HCompareNumericAndBranch>(right, fixed_right, Token::EQ); |
11233 if_same.Then(); | 11233 if_same.Then(); |
11234 if_same.ElseDeopt(Deoptimizer::kUnexpectedRHSOfBinaryOperation); | 11234 if_same.ElseDeopt(DeoptimizeReason::kUnexpectedRHSOfBinaryOperation); |
11235 right = fixed_right; | 11235 right = fixed_right; |
11236 } | 11236 } |
11237 instr = AddUncasted<HMod>(left, right); | 11237 instr = AddUncasted<HMod>(left, right); |
11238 break; | 11238 break; |
11239 } | 11239 } |
11240 case Token::DIV: | 11240 case Token::DIV: |
11241 instr = AddUncasted<HDiv>(left, right); | 11241 instr = AddUncasted<HDiv>(left, right); |
11242 break; | 11242 break; |
11243 case Token::BIT_XOR: | 11243 case Token::BIT_XOR: |
11244 case Token::BIT_AND: | 11244 case Token::BIT_AND: |
(...skipping 351 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
11596 | 11596 |
11597 HControlInstruction* HOptimizedGraphBuilder::BuildCompareInstruction( | 11597 HControlInstruction* HOptimizedGraphBuilder::BuildCompareInstruction( |
11598 Token::Value op, HValue* left, HValue* right, Type* left_type, | 11598 Token::Value op, HValue* left, HValue* right, Type* left_type, |
11599 Type* right_type, Type* combined_type, SourcePosition left_position, | 11599 Type* right_type, Type* combined_type, SourcePosition left_position, |
11600 SourcePosition right_position, PushBeforeSimulateBehavior push_sim_result, | 11600 SourcePosition right_position, PushBeforeSimulateBehavior push_sim_result, |
11601 BailoutId bailout_id) { | 11601 BailoutId bailout_id) { |
11602 // Cases handled below depend on collected type feedback. They should | 11602 // Cases handled below depend on collected type feedback. They should |
11603 // soft deoptimize when there is no type feedback. | 11603 // soft deoptimize when there is no type feedback. |
11604 if (!combined_type->IsInhabited()) { | 11604 if (!combined_type->IsInhabited()) { |
11605 Add<HDeoptimize>( | 11605 Add<HDeoptimize>( |
11606 Deoptimizer::kInsufficientTypeFeedbackForCombinedTypeOfBinaryOperation, | 11606 DeoptimizeReason:: |
| 11607 kInsufficientTypeFeedbackForCombinedTypeOfBinaryOperation, |
11607 Deoptimizer::SOFT); | 11608 Deoptimizer::SOFT); |
11608 combined_type = left_type = right_type = Type::Any(); | 11609 combined_type = left_type = right_type = Type::Any(); |
11609 } | 11610 } |
11610 | 11611 |
11611 Representation left_rep = RepresentationFor(left_type); | 11612 Representation left_rep = RepresentationFor(left_type); |
11612 Representation right_rep = RepresentationFor(right_type); | 11613 Representation right_rep = RepresentationFor(right_type); |
11613 Representation combined_rep = RepresentationFor(combined_type); | 11614 Representation combined_rep = RepresentationFor(combined_type); |
11614 | 11615 |
11615 if (combined_type->Is(Type::Receiver())) { | 11616 if (combined_type->Is(Type::Receiver())) { |
11616 if (Token::IsEqualityOp(op)) { | 11617 if (Token::IsEqualityOp(op)) { |
11617 // HCompareObjectEqAndBranch can only deal with object, so | 11618 // HCompareObjectEqAndBranch can only deal with object, so |
11618 // exclude numbers. | 11619 // exclude numbers. |
11619 if ((left->IsConstant() && | 11620 if ((left->IsConstant() && |
11620 HConstant::cast(left)->HasNumberValue()) || | 11621 HConstant::cast(left)->HasNumberValue()) || |
11621 (right->IsConstant() && | 11622 (right->IsConstant() && |
11622 HConstant::cast(right)->HasNumberValue())) { | 11623 HConstant::cast(right)->HasNumberValue())) { |
11623 Add<HDeoptimize>(Deoptimizer::kTypeMismatchBetweenFeedbackAndConstant, | 11624 Add<HDeoptimize>( |
11624 Deoptimizer::SOFT); | 11625 DeoptimizeReason::kTypeMismatchBetweenFeedbackAndConstant, |
| 11626 Deoptimizer::SOFT); |
11625 // The caller expects a branch instruction, so make it happy. | 11627 // The caller expects a branch instruction, so make it happy. |
11626 return New<HBranch>(graph()->GetConstantTrue()); | 11628 return New<HBranch>(graph()->GetConstantTrue()); |
11627 } | 11629 } |
11628 // Can we get away with map check and not instance type check? | 11630 // Can we get away with map check and not instance type check? |
11629 HValue* operand_to_check = | 11631 HValue* operand_to_check = |
11630 left->block()->block_id() < right->block()->block_id() ? left : right; | 11632 left->block()->block_id() < right->block()->block_id() ? left : right; |
11631 if (combined_type->IsClass()) { | 11633 if (combined_type->IsClass()) { |
11632 Handle<Map> map = combined_type->AsClass()->Map(); | 11634 Handle<Map> map = combined_type->AsClass()->Map(); |
11633 AddCheckMap(operand_to_check, map); | 11635 AddCheckMap(operand_to_check, map); |
11634 HCompareObjectEqAndBranch* result = | 11636 HCompareObjectEqAndBranch* result = |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
11696 return NULL; | 11698 return NULL; |
11697 } | 11699 } |
11698 } else if (combined_type->Is(Type::InternalizedString()) && | 11700 } else if (combined_type->Is(Type::InternalizedString()) && |
11699 Token::IsEqualityOp(op)) { | 11701 Token::IsEqualityOp(op)) { |
11700 // If we have a constant argument, it should be consistent with the type | 11702 // If we have a constant argument, it should be consistent with the type |
11701 // feedback (otherwise we fail assertions in HCompareObjectEqAndBranch). | 11703 // feedback (otherwise we fail assertions in HCompareObjectEqAndBranch). |
11702 if ((left->IsConstant() && | 11704 if ((left->IsConstant() && |
11703 !HConstant::cast(left)->HasInternalizedStringValue()) || | 11705 !HConstant::cast(left)->HasInternalizedStringValue()) || |
11704 (right->IsConstant() && | 11706 (right->IsConstant() && |
11705 !HConstant::cast(right)->HasInternalizedStringValue())) { | 11707 !HConstant::cast(right)->HasInternalizedStringValue())) { |
11706 Add<HDeoptimize>(Deoptimizer::kTypeMismatchBetweenFeedbackAndConstant, | 11708 Add<HDeoptimize>( |
11707 Deoptimizer::SOFT); | 11709 DeoptimizeReason::kTypeMismatchBetweenFeedbackAndConstant, |
| 11710 Deoptimizer::SOFT); |
11708 // The caller expects a branch instruction, so make it happy. | 11711 // The caller expects a branch instruction, so make it happy. |
11709 return New<HBranch>(graph()->GetConstantTrue()); | 11712 return New<HBranch>(graph()->GetConstantTrue()); |
11710 } | 11713 } |
11711 BuildCheckHeapObject(left); | 11714 BuildCheckHeapObject(left); |
11712 Add<HCheckInstanceType>(left, HCheckInstanceType::IS_INTERNALIZED_STRING); | 11715 Add<HCheckInstanceType>(left, HCheckInstanceType::IS_INTERNALIZED_STRING); |
11713 BuildCheckHeapObject(right); | 11716 BuildCheckHeapObject(right); |
11714 Add<HCheckInstanceType>(right, HCheckInstanceType::IS_INTERNALIZED_STRING); | 11717 Add<HCheckInstanceType>(right, HCheckInstanceType::IS_INTERNALIZED_STRING); |
11715 HCompareObjectEqAndBranch* result = | 11718 HCompareObjectEqAndBranch* result = |
11716 New<HCompareObjectEqAndBranch>(left, right); | 11719 New<HCompareObjectEqAndBranch>(left, right); |
11717 return result; | 11720 return result; |
(...skipping 1697 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
13415 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); | 13418 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); |
13416 } | 13419 } |
13417 | 13420 |
13418 #ifdef DEBUG | 13421 #ifdef DEBUG |
13419 graph_->Verify(false); // No full verify. | 13422 graph_->Verify(false); // No full verify. |
13420 #endif | 13423 #endif |
13421 } | 13424 } |
13422 | 13425 |
13423 } // namespace internal | 13426 } // namespace internal |
13424 } // namespace v8 | 13427 } // namespace v8 |
OLD | NEW |