Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(448)

Side by Side Diff: src/crankshaft/hydrogen.cc

Issue 2161543002: [turbofan] Add support for eager/soft deoptimization reasons. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Do the ports properly Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/crankshaft/hydrogen.h ('k') | src/crankshaft/hydrogen-instructions.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/crankshaft/hydrogen.h ('k') | src/crankshaft/hydrogen-instructions.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698