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

Side by Side Diff: src/hydrogen.cc

Issue 11377135: Don't emit code for instructions that are hiding behind an HSoftDeoptimize (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: review feedback Created 7 years, 11 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 | Annotate | Revision Log
« no previous file with comments | « src/hydrogen.h ('k') | src/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 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 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 856 matching lines...) Expand 10 before | Expand all | Expand 10 after
867 next_block_id_(0), 867 next_block_id_(0),
868 entry_block_(NULL), 868 entry_block_(NULL),
869 blocks_(8, info->zone()), 869 blocks_(8, info->zone()),
870 values_(16, info->zone()), 870 values_(16, info->zone()),
871 phi_list_(NULL), 871 phi_list_(NULL),
872 uint32_instructions_(NULL), 872 uint32_instructions_(NULL),
873 info_(info), 873 info_(info),
874 zone_(info->zone()), 874 zone_(info->zone()),
875 is_recursive_(false), 875 is_recursive_(false),
876 use_optimistic_licm_(false), 876 use_optimistic_licm_(false),
877 has_soft_deoptimize_(false),
877 type_change_checksum_(0) { 878 type_change_checksum_(0) {
878 if (info->IsStub()) { 879 if (info->IsStub()) {
879 start_environment_ = 880 start_environment_ =
880 new(zone_) HEnvironment(zone_); 881 new(zone_) HEnvironment(zone_);
881 } else { 882 } else {
882 start_environment_ = 883 start_environment_ =
883 new(zone_) HEnvironment(NULL, info->scope(), info->closure(), zone_); 884 new(zone_) HEnvironment(NULL, info->scope(), info->closure(), zone_);
884 } 885 }
885 start_environment_->set_ast_id(BailoutId::FunctionEntry()); 886 start_environment_->set_ast_id(BailoutId::FunctionEntry());
886 entry_block_ = CreateBasicBlock(); 887 entry_block_ = CreateBasicBlock();
(...skipping 347 matching lines...) Expand 10 before | Expand all | Expand 10 after
1234 block->AssignCommonDominator(block->predecessors()->first()); 1235 block->AssignCommonDominator(block->predecessors()->first());
1235 block->AssignLoopSuccessorDominators(); 1236 block->AssignLoopSuccessorDominators();
1236 } else { 1237 } else {
1237 for (int j = blocks_[i]->predecessors()->length() - 1; j >= 0; --j) { 1238 for (int j = blocks_[i]->predecessors()->length() - 1; j >= 0; --j) {
1238 blocks_[i]->AssignCommonDominator(blocks_[i]->predecessors()->at(j)); 1239 blocks_[i]->AssignCommonDominator(blocks_[i]->predecessors()->at(j));
1239 } 1240 }
1240 } 1241 }
1241 } 1242 }
1242 } 1243 }
1243 1244
1245
1244 // Mark all blocks that are dominated by an unconditional soft deoptimize to 1246 // Mark all blocks that are dominated by an unconditional soft deoptimize to
1245 // prevent code motion across those blocks. 1247 // prevent code motion across those blocks.
1246 void HGraph::PropagateDeoptimizingMark() { 1248 void HGraph::PropagateDeoptimizingMark() {
1247 HPhase phase("H_Propagate deoptimizing mark", this); 1249 HPhase phase("H_Propagate deoptimizing mark", this);
1250 // Skip this phase if there is nothing to be done anyway.
1251 if (!has_soft_deoptimize()) return;
1248 MarkAsDeoptimizingRecursively(entry_block()); 1252 MarkAsDeoptimizingRecursively(entry_block());
1253 NullifyUnreachableInstructions();
1249 } 1254 }
1250 1255
1256
1251 void HGraph::MarkAsDeoptimizingRecursively(HBasicBlock* block) { 1257 void HGraph::MarkAsDeoptimizingRecursively(HBasicBlock* block) {
1252 for (int i = 0; i < block->dominated_blocks()->length(); ++i) { 1258 for (int i = 0; i < block->dominated_blocks()->length(); ++i) {
1253 HBasicBlock* dominated = block->dominated_blocks()->at(i); 1259 HBasicBlock* dominated = block->dominated_blocks()->at(i);
1254 if (block->IsDeoptimizing()) dominated->MarkAsDeoptimizing(); 1260 if (block->IsDeoptimizing()) dominated->MarkAsDeoptimizing();
1255 MarkAsDeoptimizingRecursively(dominated); 1261 MarkAsDeoptimizingRecursively(dominated);
1256 } 1262 }
1257 } 1263 }
1258 1264
1265
1266 void HGraph::NullifyUnreachableInstructions() {
1267 int block_count = blocks_.length();
1268 for (int i = 0; i < block_count; ++i) {
1269 HBasicBlock* block = blocks_.at(i);
1270 bool nullify = false;
1271 const ZoneList<HBasicBlock*>* predecessors = block->predecessors();
1272 int predecessors_length = predecessors->length();
1273 bool all_predecessors_deoptimizing = (predecessors_length > 0);
1274 for (int j = 0; j < predecessors_length; ++j) {
1275 if (!predecessors->at(j)->IsDeoptimizing()) {
1276 all_predecessors_deoptimizing = false;
1277 break;
1278 }
1279 }
1280 if (all_predecessors_deoptimizing) nullify = true;
1281 for (HInstruction* instr = block->first(); instr != NULL;
1282 instr = instr->next()) {
1283 // Leave the basic structure of the graph intact.
1284 if (instr->IsBlockEntry()) continue;
1285 if (instr->IsControlInstruction()) continue;
1286 if (instr->IsSimulate()) continue;
1287 if (instr->IsEnterInlined()) continue;
1288 if (instr->IsLeaveInlined()) continue;
1289 if (nullify) {
1290 HInstruction* last_dummy = NULL;
1291 for (int j = 0; j < instr->OperandCount(); ++j) {
1292 HValue* operand = instr->OperandAt(j);
1293 // Insert an HDummyUse for each operand, unless the operand
1294 // is an HDummyUse itself. If it's even from the same block,
1295 // remember it as a potential replacement for the instruction.
1296 if (operand->IsDummyUse()) {
1297 if (operand->block() == instr->block() &&
1298 last_dummy == NULL) {
1299 last_dummy = HInstruction::cast(operand);
1300 }
1301 continue;
1302 }
1303 HDummyUse* dummy = new(zone()) HDummyUse(operand);
1304 dummy->InsertBefore(instr);
1305 last_dummy = dummy;
1306 }
1307 if (last_dummy == NULL) last_dummy = GetConstant1();
1308 instr->DeleteAndReplaceWith(last_dummy);
1309 continue;
1310 }
1311 if (instr->IsSoftDeoptimize()) {
1312 ASSERT(block->IsDeoptimizing());
1313 nullify = true;
1314 }
1315 }
1316 }
1317 }
1318
1319
1259 void HGraph::EliminateRedundantPhis() { 1320 void HGraph::EliminateRedundantPhis() {
1260 HPhase phase("H_Redundant phi elimination", this); 1321 HPhase phase("H_Redundant phi elimination", this);
1261 1322
1262 // Worklist of phis that can potentially be eliminated. Initialized with 1323 // Worklist of phis that can potentially be eliminated. Initialized with
1263 // all phi nodes. When elimination of a phi node modifies another phi node 1324 // all phi nodes. When elimination of a phi node modifies another phi node
1264 // the modified phi node is added to the worklist. 1325 // the modified phi node is added to the worklist.
1265 ZoneList<HPhi*> worklist(blocks_.length(), zone()); 1326 ZoneList<HPhi*> worklist(blocks_.length(), zone());
1266 for (int i = 0; i < blocks_.length(); ++i) { 1327 for (int i = 0; i < blocks_.length(); ++i) {
1267 worklist.AddAll(*blocks_[i]->phis(), zone()); 1328 worklist.AddAll(*blocks_[i]->phis(), zone());
1268 } 1329 }
(...skipping 2681 matching lines...) Expand 10 before | Expand all | Expand 10 after
3950 current_block()->AddPhi(instr); 4011 current_block()->AddPhi(instr);
3951 } 4012 }
3952 4013
3953 4014
3954 void HOptimizedGraphBuilder::PushAndAdd(HInstruction* instr) { 4015 void HOptimizedGraphBuilder::PushAndAdd(HInstruction* instr) {
3955 Push(instr); 4016 Push(instr);
3956 AddInstruction(instr); 4017 AddInstruction(instr);
3957 } 4018 }
3958 4019
3959 4020
4021 void HOptimizedGraphBuilder::AddSoftDeoptimize() {
4022 if (FLAG_always_opt) return;
4023 if (current_block()->IsDeoptimizing()) return;
4024 AddInstruction(new(zone()) HSoftDeoptimize());
4025 current_block()->MarkAsDeoptimizing();
4026 graph()->set_has_soft_deoptimize(true);
4027 }
4028
4029
3960 template <class Instruction> 4030 template <class Instruction>
3961 HInstruction* HOptimizedGraphBuilder::PreProcessCall(Instruction* call) { 4031 HInstruction* HOptimizedGraphBuilder::PreProcessCall(Instruction* call) {
3962 int count = call->argument_count(); 4032 int count = call->argument_count();
3963 ZoneList<HValue*> arguments(count, zone()); 4033 ZoneList<HValue*> arguments(count, zone());
3964 for (int i = 0; i < count; ++i) { 4034 for (int i = 0; i < count; ++i) {
3965 arguments.Add(Pop(), zone()); 4035 arguments.Add(Pop(), zone());
3966 } 4036 }
3967 4037
3968 while (!arguments.is_empty()) { 4038 while (!arguments.is_empty()) {
3969 AddInstruction(new(zone()) HPushArgument(arguments.RemoveLast())); 4039 AddInstruction(new(zone()) HPushArgument(arguments.RemoveLast()));
(...skipping 2149 matching lines...) Expand 10 before | Expand all | Expand 10 after
6119 int offset = (index * kPointerSize) + FixedArray::kHeaderSize; 6189 int offset = (index * kPointerSize) + FixedArray::kHeaderSize;
6120 return new(zone()) HLoadNamedField(object, false, offset); 6190 return new(zone()) HLoadNamedField(object, false, offset);
6121 } 6191 }
6122 } 6192 }
6123 6193
6124 6194
6125 HInstruction* HOptimizedGraphBuilder::BuildLoadNamedGeneric( 6195 HInstruction* HOptimizedGraphBuilder::BuildLoadNamedGeneric(
6126 HValue* object, 6196 HValue* object,
6127 Handle<String> name, 6197 Handle<String> name,
6128 Property* expr) { 6198 Property* expr) {
6129 if (expr->IsUninitialized() && !FLAG_always_opt) { 6199 if (expr->IsUninitialized()) {
6130 AddInstruction(new(zone()) HSoftDeoptimize); 6200 AddSoftDeoptimize();
6131 current_block()->MarkAsDeoptimizing();
6132 } 6201 }
6133 HValue* context = environment()->LookupContext(); 6202 HValue* context = environment()->LookupContext();
6134 return new(zone()) HLoadNamedGeneric(context, object, name); 6203 return new(zone()) HLoadNamedGeneric(context, object, name);
6135 } 6204 }
6136 6205
6137 6206
6138 HInstruction* HOptimizedGraphBuilder::BuildCallGetter( 6207 HInstruction* HOptimizedGraphBuilder::BuildCallGetter(
6139 HValue* object, 6208 HValue* object,
6140 Handle<Map> map, 6209 Handle<Map> map,
6141 Handle<JSFunction> getter, 6210 Handle<JSFunction> getter,
(...skipping 1871 matching lines...) Expand 10 before | Expand all | Expand 10 after
8013 8082
8014 void HOptimizedGraphBuilder::VisitSub(UnaryOperation* expr) { 8083 void HOptimizedGraphBuilder::VisitSub(UnaryOperation* expr) {
8015 CHECK_ALIVE(VisitForValue(expr->expression())); 8084 CHECK_ALIVE(VisitForValue(expr->expression()));
8016 HValue* value = Pop(); 8085 HValue* value = Pop();
8017 HValue* context = environment()->LookupContext(); 8086 HValue* context = environment()->LookupContext();
8018 HInstruction* instr = 8087 HInstruction* instr =
8019 new(zone()) HMul(context, value, graph()->GetConstantMinus1()); 8088 new(zone()) HMul(context, value, graph()->GetConstantMinus1());
8020 TypeInfo info = oracle()->UnaryType(expr); 8089 TypeInfo info = oracle()->UnaryType(expr);
8021 Representation rep = ToRepresentation(info); 8090 Representation rep = ToRepresentation(info);
8022 if (info.IsUninitialized()) { 8091 if (info.IsUninitialized()) {
8023 AddInstruction(new(zone()) HSoftDeoptimize); 8092 AddSoftDeoptimize();
8024 current_block()->MarkAsDeoptimizing();
8025 info = TypeInfo::Unknown(); 8093 info = TypeInfo::Unknown();
8026 } 8094 }
8027 HBinaryOperation::cast(instr)->set_observed_input_representation(rep, rep); 8095 HBinaryOperation::cast(instr)->set_observed_input_representation(rep, rep);
8028 return ast_context()->ReturnInstruction(instr, expr->id()); 8096 return ast_context()->ReturnInstruction(instr, expr->id());
8029 } 8097 }
8030 8098
8031 8099
8032 void HOptimizedGraphBuilder::VisitBitNot(UnaryOperation* expr) { 8100 void HOptimizedGraphBuilder::VisitBitNot(UnaryOperation* expr) {
8033 CHECK_ALIVE(VisitForValue(expr->expression())); 8101 CHECK_ALIVE(VisitForValue(expr->expression()));
8034 HValue* value = Pop(); 8102 HValue* value = Pop();
8035 TypeInfo info = oracle()->UnaryType(expr); 8103 TypeInfo info = oracle()->UnaryType(expr);
8036 if (info.IsUninitialized()) { 8104 if (info.IsUninitialized()) {
8037 AddInstruction(new(zone()) HSoftDeoptimize); 8105 AddSoftDeoptimize();
8038 current_block()->MarkAsDeoptimizing();
8039 } 8106 }
8040 HInstruction* instr = new(zone()) HBitNot(value); 8107 HInstruction* instr = new(zone()) HBitNot(value);
8041 return ast_context()->ReturnInstruction(instr, expr->id()); 8108 return ast_context()->ReturnInstruction(instr, expr->id());
8042 } 8109 }
8043 8110
8044 8111
8045 void HOptimizedGraphBuilder::VisitNot(UnaryOperation* expr) { 8112 void HOptimizedGraphBuilder::VisitNot(UnaryOperation* expr) {
8046 if (ast_context()->IsTest()) { 8113 if (ast_context()->IsTest()) {
8047 TestContext* context = TestContext::cast(ast_context()); 8114 TestContext* context = TestContext::cast(ast_context());
8048 VisitForControl(expr->expression(), 8115 VisitForControl(expr->expression(),
(...skipping 335 matching lines...) Expand 10 before | Expand all | Expand 10 after
8384 HValue* right) { 8451 HValue* right) {
8385 HValue* context = environment()->LookupContext(); 8452 HValue* context = environment()->LookupContext();
8386 TypeInfo left_info, right_info, result_info, combined_info; 8453 TypeInfo left_info, right_info, result_info, combined_info;
8387 oracle()->BinaryType(expr, &left_info, &right_info, &result_info); 8454 oracle()->BinaryType(expr, &left_info, &right_info, &result_info);
8388 Representation left_rep = ToRepresentation(left_info); 8455 Representation left_rep = ToRepresentation(left_info);
8389 Representation right_rep = ToRepresentation(right_info); 8456 Representation right_rep = ToRepresentation(right_info);
8390 Representation result_rep = ToRepresentation(result_info); 8457 Representation result_rep = ToRepresentation(result_info);
8391 if (left_info.IsUninitialized()) { 8458 if (left_info.IsUninitialized()) {
8392 // Can't have initialized one but not the other. 8459 // Can't have initialized one but not the other.
8393 ASSERT(right_info.IsUninitialized()); 8460 ASSERT(right_info.IsUninitialized());
8394 AddInstruction(new(zone()) HSoftDeoptimize); 8461 AddSoftDeoptimize();
8395 current_block()->MarkAsDeoptimizing();
8396 left_info = right_info = TypeInfo::Unknown(); 8462 left_info = right_info = TypeInfo::Unknown();
8397 } 8463 }
8398 HInstruction* instr = NULL; 8464 HInstruction* instr = NULL;
8399 switch (expr->op()) { 8465 switch (expr->op()) {
8400 case Token::ADD: 8466 case Token::ADD:
8401 if (left_info.IsString() && right_info.IsString()) { 8467 if (left_info.IsString() && right_info.IsString()) {
8402 AddInstruction(new(zone()) HCheckNonSmi(left)); 8468 AddInstruction(new(zone()) HCheckNonSmi(left));
8403 AddInstruction(HCheckInstanceType::NewIsString(left, zone())); 8469 AddInstruction(HCheckInstanceType::NewIsString(left, zone()));
8404 AddInstruction(new(zone()) HCheckNonSmi(right)); 8470 AddInstruction(new(zone()) HCheckNonSmi(right));
8405 AddInstruction(HCheckInstanceType::NewIsString(right, zone())); 8471 AddInstruction(HCheckInstanceType::NewIsString(right, zone()));
(...skipping 293 matching lines...) Expand 10 before | Expand all | Expand 10 after
8699 } 8765 }
8700 8766
8701 TypeInfo left_type, right_type, overall_type_info; 8767 TypeInfo left_type, right_type, overall_type_info;
8702 oracle()->CompareType(expr, &left_type, &right_type, &overall_type_info); 8768 oracle()->CompareType(expr, &left_type, &right_type, &overall_type_info);
8703 Representation combined_rep = ToRepresentation(overall_type_info); 8769 Representation combined_rep = ToRepresentation(overall_type_info);
8704 Representation left_rep = ToRepresentation(left_type); 8770 Representation left_rep = ToRepresentation(left_type);
8705 Representation right_rep = ToRepresentation(right_type); 8771 Representation right_rep = ToRepresentation(right_type);
8706 // Check if this expression was ever executed according to type feedback. 8772 // Check if this expression was ever executed according to type feedback.
8707 // Note that for the special typeof/null/undefined cases we get unknown here. 8773 // Note that for the special typeof/null/undefined cases we get unknown here.
8708 if (overall_type_info.IsUninitialized()) { 8774 if (overall_type_info.IsUninitialized()) {
8709 AddInstruction(new(zone()) HSoftDeoptimize); 8775 AddSoftDeoptimize();
8710 current_block()->MarkAsDeoptimizing();
8711 overall_type_info = left_type = right_type = TypeInfo::Unknown(); 8776 overall_type_info = left_type = right_type = TypeInfo::Unknown();
8712 } 8777 }
8713 8778
8714 CHECK_ALIVE(VisitForValue(expr->left())); 8779 CHECK_ALIVE(VisitForValue(expr->left()));
8715 CHECK_ALIVE(VisitForValue(expr->right())); 8780 CHECK_ALIVE(VisitForValue(expr->right()));
8716 8781
8717 HValue* context = environment()->LookupContext(); 8782 HValue* context = environment()->LookupContext();
8718 HValue* right = Pop(); 8783 HValue* right = Pop();
8719 HValue* left = Pop(); 8784 HValue* left = Pop();
8720 Token::Value op = expr->op(); 8785 Token::Value op = expr->op();
(...skipping 1449 matching lines...) Expand 10 before | Expand all | Expand 10 after
10170 } 10235 }
10171 } 10236 }
10172 10237
10173 #ifdef DEBUG 10238 #ifdef DEBUG
10174 if (graph_ != NULL) graph_->Verify(false); // No full verify. 10239 if (graph_ != NULL) graph_->Verify(false); // No full verify.
10175 if (allocator_ != NULL) allocator_->Verify(); 10240 if (allocator_ != NULL) allocator_->Verify();
10176 #endif 10241 #endif
10177 } 10242 }
10178 10243
10179 } } // namespace v8::internal 10244 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/hydrogen.h ('k') | src/hydrogen-instructions.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698