| OLD | NEW |
| 1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // Copyright 2015 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/compiler/bytecode-graph-builder.h" | 5 #include "src/compiler/bytecode-graph-builder.h" |
| 6 | 6 |
| 7 #include "src/compiler/bytecode-branch-analysis.h" |
| 7 #include "src/compiler/linkage.h" | 8 #include "src/compiler/linkage.h" |
| 8 #include "src/compiler/operator-properties.h" | 9 #include "src/compiler/operator-properties.h" |
| 9 #include "src/interpreter/bytecode-array-iterator.h" | |
| 10 #include "src/interpreter/bytecodes.h" | 10 #include "src/interpreter/bytecodes.h" |
| 11 | 11 |
| 12 namespace v8 { | 12 namespace v8 { |
| 13 namespace internal { | 13 namespace internal { |
| 14 namespace compiler { | 14 namespace compiler { |
| 15 | 15 |
| 16 // Issues: | 16 // Issues: |
| 17 // - Need to deal with FrameState / FrameStateBeforeAndAfter / StateValue. | 17 // - Need to deal with FrameState / FrameStateBeforeAndAfter / StateValue. |
| 18 // - Scopes - intimately tied to AST. Need to eval what is needed. | 18 // - Scopes - intimately tied to AST. Need to eval what is needed. |
| 19 // - Need to resolve closure parameter treatment. | 19 // - Need to resolve closure parameter treatment. |
| (...skipping 28 matching lines...) Expand all Loading... |
| 48 // Registers | 48 // Registers |
| 49 register_base_ = static_cast<int>(values()->size()); | 49 register_base_ = static_cast<int>(values()->size()); |
| 50 Node* undefined_constant = builder->jsgraph()->UndefinedConstant(); | 50 Node* undefined_constant = builder->jsgraph()->UndefinedConstant(); |
| 51 values()->insert(values()->end(), register_count, undefined_constant); | 51 values()->insert(values()->end(), register_count, undefined_constant); |
| 52 | 52 |
| 53 // Accumulator | 53 // Accumulator |
| 54 accumulator_ = undefined_constant; | 54 accumulator_ = undefined_constant; |
| 55 } | 55 } |
| 56 | 56 |
| 57 | 57 |
| 58 BytecodeGraphBuilder::Environment::Environment( |
| 59 const BytecodeGraphBuilder::Environment* other) |
| 60 : builder_(other->builder_), |
| 61 register_count_(other->register_count_), |
| 62 parameter_count_(other->parameter_count_), |
| 63 accumulator_(other->accumulator_), |
| 64 context_(other->context_), |
| 65 control_dependency_(other->control_dependency_), |
| 66 effect_dependency_(other->effect_dependency_), |
| 67 values_(other->zone()), |
| 68 register_base_(other->register_base_) { |
| 69 values_ = other->values_; |
| 70 } |
| 71 |
| 72 |
| 58 int BytecodeGraphBuilder::Environment::RegisterToValuesIndex( | 73 int BytecodeGraphBuilder::Environment::RegisterToValuesIndex( |
| 59 interpreter::Register the_register) const { | 74 interpreter::Register the_register) const { |
| 60 if (the_register.is_parameter()) { | 75 if (the_register.is_parameter()) { |
| 61 return the_register.ToParameterIndex(parameter_count()); | 76 return the_register.ToParameterIndex(parameter_count()); |
| 62 } else { | 77 } else { |
| 63 return the_register.index() + register_base(); | 78 return the_register.index() + register_base(); |
| 64 } | 79 } |
| 65 } | 80 } |
| 66 | 81 |
| 67 | 82 |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 100 bool BytecodeGraphBuilder::Environment::IsMarkedAsUnreachable() const { | 115 bool BytecodeGraphBuilder::Environment::IsMarkedAsUnreachable() const { |
| 101 return GetControlDependency()->opcode() == IrOpcode::kDead; | 116 return GetControlDependency()->opcode() == IrOpcode::kDead; |
| 102 } | 117 } |
| 103 | 118 |
| 104 | 119 |
| 105 void BytecodeGraphBuilder::Environment::MarkAsUnreachable() { | 120 void BytecodeGraphBuilder::Environment::MarkAsUnreachable() { |
| 106 UpdateControlDependency(builder()->jsgraph()->Dead()); | 121 UpdateControlDependency(builder()->jsgraph()->Dead()); |
| 107 } | 122 } |
| 108 | 123 |
| 109 | 124 |
| 125 BytecodeGraphBuilder::Environment* |
| 126 BytecodeGraphBuilder::Environment::CopyForLoop() { |
| 127 PrepareForLoop(); |
| 128 return new (zone()) Environment(this); |
| 129 } |
| 130 |
| 131 |
| 132 BytecodeGraphBuilder::Environment* |
| 133 BytecodeGraphBuilder::Environment::CopyForConditional() const { |
| 134 return new (zone()) Environment(this); |
| 135 } |
| 136 |
| 137 |
| 138 void BytecodeGraphBuilder::Environment::Merge( |
| 139 BytecodeGraphBuilder::Environment* other) { |
| 140 // Nothing to do if the other environment is dead. |
| 141 if (other->IsMarkedAsUnreachable()) { |
| 142 return; |
| 143 } |
| 144 |
| 145 // Create a merge of the control dependencies of both environments and update |
| 146 // the current environment's control dependency accordingly. |
| 147 Node* control = builder()->MergeControl(GetControlDependency(), |
| 148 other->GetControlDependency()); |
| 149 UpdateControlDependency(control); |
| 150 |
| 151 // Create a merge of the effect dependencies of both environments and update |
| 152 // the current environment's effect dependency accordingly. |
| 153 Node* effect = builder()->MergeEffect(GetEffectDependency(), |
| 154 other->GetEffectDependency(), control); |
| 155 UpdateEffectDependency(effect); |
| 156 |
| 157 // Introduce Phi nodes for values that have differing input at merge points, |
| 158 // potentially extending an existing Phi node if possible. |
| 159 accumulator_ = |
| 160 builder()->MergeValue(accumulator_, other->accumulator_, control); |
| 161 context_ = builder()->MergeValue(context_, other->context_, control); |
| 162 for (size_t i = 0; i < values_.size(); i++) { |
| 163 values_[i] = builder()->MergeValue(values_[i], other->values_[i], control); |
| 164 } |
| 165 } |
| 166 |
| 167 |
| 168 void BytecodeGraphBuilder::Environment::PrepareForLoop() { |
| 169 // Create a control node for the loop header. |
| 170 Node* control = builder()->NewLoop(); |
| 171 |
| 172 // Create a Phi for external effects. |
| 173 Node* effect = builder()->NewEffectPhi(1, GetEffectDependency(), control); |
| 174 UpdateEffectDependency(effect); |
| 175 |
| 176 // Assume everything in the loop is updated. |
| 177 accumulator_ = builder()->NewPhi(1, accumulator_, control); |
| 178 context_ = builder()->NewPhi(1, context_, control); |
| 179 int size = static_cast<int>(values()->size()); |
| 180 for (int i = 0; i < size; i++) { |
| 181 values()->at(i) = builder()->NewPhi(1, values()->at(i), control); |
| 182 } |
| 183 |
| 184 // Connect to the loop end. |
| 185 Node* terminate = builder()->graph()->NewNode( |
| 186 builder()->common()->Terminate(), effect, control); |
| 187 builder()->exit_controls_.push_back(terminate); |
| 188 } |
| 189 |
| 190 |
| 110 BytecodeGraphBuilder::BytecodeGraphBuilder(Zone* local_zone, | 191 BytecodeGraphBuilder::BytecodeGraphBuilder(Zone* local_zone, |
| 111 CompilationInfo* compilation_info, | 192 CompilationInfo* compilation_info, |
| 112 JSGraph* jsgraph) | 193 JSGraph* jsgraph) |
| 113 : local_zone_(local_zone), | 194 : local_zone_(local_zone), |
| 114 info_(compilation_info), | 195 info_(compilation_info), |
| 115 jsgraph_(jsgraph), | 196 jsgraph_(jsgraph), |
| 197 merge_environments_(local_zone), |
| 198 loop_header_environments_(local_zone), |
| 116 input_buffer_size_(0), | 199 input_buffer_size_(0), |
| 117 input_buffer_(nullptr), | 200 input_buffer_(nullptr), |
| 118 exit_controls_(local_zone) { | 201 exit_controls_(local_zone) { |
| 119 bytecode_array_ = handle(info()->shared_info()->bytecode_array()); | 202 bytecode_array_ = handle(info()->shared_info()->bytecode_array()); |
| 120 } | 203 } |
| 121 | 204 |
| 122 | 205 |
| 123 Node* BytecodeGraphBuilder::GetNewTarget() { | 206 Node* BytecodeGraphBuilder::GetNewTarget() { |
| 124 if (!new_target_.is_set()) { | 207 if (!new_target_.is_set()) { |
| 125 int params = bytecode_array()->parameter_count(); | 208 int params = bytecode_array()->parameter_count(); |
| (...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 240 | 323 |
| 241 | 324 |
| 242 void BytecodeGraphBuilder::CreateGraphBody(bool stack_check) { | 325 void BytecodeGraphBuilder::CreateGraphBody(bool stack_check) { |
| 243 // TODO(oth): Review ast-graph-builder equivalent, i.e. arguments | 326 // TODO(oth): Review ast-graph-builder equivalent, i.e. arguments |
| 244 // object setup, this function variable if used, tracing hooks. | 327 // object setup, this function variable if used, tracing hooks. |
| 245 VisitBytecodes(); | 328 VisitBytecodes(); |
| 246 } | 329 } |
| 247 | 330 |
| 248 | 331 |
| 249 void BytecodeGraphBuilder::VisitBytecodes() { | 332 void BytecodeGraphBuilder::VisitBytecodes() { |
| 333 BytecodeBranchAnalysis analysis(bytecode_array(), local_zone()); |
| 334 analysis.Analyze(); |
| 335 set_branch_analysis(&analysis); |
| 250 interpreter::BytecodeArrayIterator iterator(bytecode_array()); | 336 interpreter::BytecodeArrayIterator iterator(bytecode_array()); |
| 337 set_bytecode_iterator(&iterator); |
| 251 while (!iterator.done()) { | 338 while (!iterator.done()) { |
| 252 switch (iterator.current_bytecode()) { | 339 int current_offset = iterator.current_offset(); |
| 340 if (analysis.is_reachable(current_offset)) { |
| 341 MergeEnvironmentsOfForwardBranches(current_offset); |
| 342 BuildLoopHeaderForBackwardBranches(current_offset); |
| 343 |
| 344 switch (iterator.current_bytecode()) { |
| 253 #define BYTECODE_CASE(name, ...) \ | 345 #define BYTECODE_CASE(name, ...) \ |
| 254 case interpreter::Bytecode::k##name: \ | 346 case interpreter::Bytecode::k##name: \ |
| 255 Visit##name(iterator); \ | 347 Visit##name(iterator); \ |
| 256 break; | 348 break; |
| 257 BYTECODE_LIST(BYTECODE_CASE) | 349 BYTECODE_LIST(BYTECODE_CASE) |
| 258 #undef BYTECODE_CODE | 350 #undef BYTECODE_CODE |
| 351 } |
| 259 } | 352 } |
| 260 iterator.Advance(); | 353 iterator.Advance(); |
| 261 } | 354 } |
| 355 set_branch_analysis(nullptr); |
| 356 set_bytecode_iterator(nullptr); |
| 262 } | 357 } |
| 263 | 358 |
| 264 | 359 |
| 265 void BytecodeGraphBuilder::VisitLdaZero( | 360 void BytecodeGraphBuilder::VisitLdaZero( |
| 266 const interpreter::BytecodeArrayIterator& iterator) { | 361 const interpreter::BytecodeArrayIterator& iterator) { |
| 267 Node* node = jsgraph()->ZeroConstant(); | 362 Node* node = jsgraph()->ZeroConstant(); |
| 268 environment()->BindAccumulator(node); | 363 environment()->BindAccumulator(node); |
| 269 } | 364 } |
| 270 | 365 |
| 271 | 366 |
| (...skipping 895 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1167 | 1262 |
| 1168 | 1263 |
| 1169 void BytecodeGraphBuilder::VisitToObject( | 1264 void BytecodeGraphBuilder::VisitToObject( |
| 1170 const interpreter::BytecodeArrayIterator& iterator) { | 1265 const interpreter::BytecodeArrayIterator& iterator) { |
| 1171 BuildCastOperator(javascript()->ToObject(), iterator); | 1266 BuildCastOperator(javascript()->ToObject(), iterator); |
| 1172 } | 1267 } |
| 1173 | 1268 |
| 1174 | 1269 |
| 1175 void BytecodeGraphBuilder::VisitJump( | 1270 void BytecodeGraphBuilder::VisitJump( |
| 1176 const interpreter::BytecodeArrayIterator& iterator) { | 1271 const interpreter::BytecodeArrayIterator& iterator) { |
| 1177 UNIMPLEMENTED(); | 1272 BuildJump(); |
| 1178 } | 1273 } |
| 1179 | 1274 |
| 1180 | 1275 |
| 1181 void BytecodeGraphBuilder::VisitJumpConstant( | 1276 void BytecodeGraphBuilder::VisitJumpConstant( |
| 1182 const interpreter::BytecodeArrayIterator& iterator) { | 1277 const interpreter::BytecodeArrayIterator& iterator) { |
| 1183 UNIMPLEMENTED(); | 1278 BuildJump(); |
| 1184 } | 1279 } |
| 1185 | 1280 |
| 1186 | 1281 |
| 1187 void BytecodeGraphBuilder::VisitJumpIfTrue( | 1282 void BytecodeGraphBuilder::VisitJumpIfTrue( |
| 1188 const interpreter::BytecodeArrayIterator& iterator) { | 1283 const interpreter::BytecodeArrayIterator& iterator) { |
| 1189 UNIMPLEMENTED(); | 1284 Node* condition = BuildCondition(jsgraph()->TrueConstant()); |
| 1285 BuildConditionalJump(condition); |
| 1190 } | 1286 } |
| 1191 | 1287 |
| 1192 | 1288 |
| 1193 void BytecodeGraphBuilder::VisitJumpIfTrueConstant( | 1289 void BytecodeGraphBuilder::VisitJumpIfTrueConstant( |
| 1194 const interpreter::BytecodeArrayIterator& iterator) { | 1290 const interpreter::BytecodeArrayIterator& iterator) { |
| 1195 UNIMPLEMENTED(); | 1291 Node* condition = BuildCondition(jsgraph()->TrueConstant()); |
| 1292 BuildConditionalJump(condition); |
| 1196 } | 1293 } |
| 1197 | 1294 |
| 1198 | 1295 |
| 1199 void BytecodeGraphBuilder::VisitJumpIfFalse( | 1296 void BytecodeGraphBuilder::VisitJumpIfFalse( |
| 1200 const interpreter::BytecodeArrayIterator& iterator) { | 1297 const interpreter::BytecodeArrayIterator& iterator) { |
| 1201 UNIMPLEMENTED(); | 1298 Node* condition = BuildCondition(jsgraph()->FalseConstant()); |
| 1299 BuildConditionalJump(condition); |
| 1202 } | 1300 } |
| 1203 | 1301 |
| 1204 | 1302 |
| 1205 void BytecodeGraphBuilder::VisitJumpIfFalseConstant( | 1303 void BytecodeGraphBuilder::VisitJumpIfFalseConstant( |
| 1206 const interpreter::BytecodeArrayIterator& iterator) { | 1304 const interpreter::BytecodeArrayIterator& iterator) { |
| 1207 UNIMPLEMENTED(); | 1305 Node* condition = BuildCondition(jsgraph()->FalseConstant()); |
| 1306 BuildConditionalJump(condition); |
| 1208 } | 1307 } |
| 1209 | 1308 |
| 1210 | 1309 |
| 1211 void BytecodeGraphBuilder::VisitJumpIfToBooleanTrue( | 1310 void BytecodeGraphBuilder::VisitJumpIfToBooleanTrue( |
| 1212 const interpreter::BytecodeArrayIterator& iterator) { | 1311 const interpreter::BytecodeArrayIterator& iterator) { |
| 1213 UNIMPLEMENTED(); | 1312 Node* condition = BuildToBooleanCondition(jsgraph()->TrueConstant()); |
| 1313 BuildConditionalJump(condition); |
| 1214 } | 1314 } |
| 1215 | 1315 |
| 1216 | 1316 |
| 1217 void BytecodeGraphBuilder::VisitJumpIfToBooleanTrueConstant( | 1317 void BytecodeGraphBuilder::VisitJumpIfToBooleanTrueConstant( |
| 1218 const interpreter::BytecodeArrayIterator& iterator) { | 1318 const interpreter::BytecodeArrayIterator& iterator) { |
| 1219 UNIMPLEMENTED(); | 1319 Node* condition = BuildToBooleanCondition(jsgraph()->TrueConstant()); |
| 1320 BuildConditionalJump(condition); |
| 1220 } | 1321 } |
| 1221 | 1322 |
| 1222 | 1323 |
| 1223 void BytecodeGraphBuilder::VisitJumpIfToBooleanFalse( | 1324 void BytecodeGraphBuilder::VisitJumpIfToBooleanFalse( |
| 1224 const interpreter::BytecodeArrayIterator& iterator) { | 1325 const interpreter::BytecodeArrayIterator& iterator) { |
| 1225 UNIMPLEMENTED(); | 1326 Node* condition = BuildToBooleanCondition(jsgraph()->FalseConstant()); |
| 1327 BuildConditionalJump(condition); |
| 1226 } | 1328 } |
| 1227 | 1329 |
| 1228 | 1330 |
| 1229 void BytecodeGraphBuilder::VisitJumpIfToBooleanFalseConstant( | 1331 void BytecodeGraphBuilder::VisitJumpIfToBooleanFalseConstant( |
| 1230 const interpreter::BytecodeArrayIterator& iterator) { | 1332 const interpreter::BytecodeArrayIterator& iterator) { |
| 1231 UNIMPLEMENTED(); | 1333 Node* condition = BuildToBooleanCondition(jsgraph()->FalseConstant()); |
| 1334 BuildConditionalJump(condition); |
| 1232 } | 1335 } |
| 1233 | 1336 |
| 1234 | 1337 |
| 1235 void BytecodeGraphBuilder::VisitJumpIfNull( | 1338 void BytecodeGraphBuilder::VisitJumpIfNull( |
| 1236 const interpreter::BytecodeArrayIterator& iterator) { | 1339 const interpreter::BytecodeArrayIterator& iterator) { |
| 1237 UNIMPLEMENTED(); | 1340 Node* condition = BuildCondition(jsgraph()->NullConstant()); |
| 1341 BuildConditionalJump(condition); |
| 1238 } | 1342 } |
| 1239 | 1343 |
| 1240 | 1344 |
| 1241 void BytecodeGraphBuilder::VisitJumpIfNullConstant( | 1345 void BytecodeGraphBuilder::VisitJumpIfNullConstant( |
| 1242 const interpreter::BytecodeArrayIterator& iterator) { | 1346 const interpreter::BytecodeArrayIterator& iterator) { |
| 1243 UNIMPLEMENTED(); | 1347 Node* condition = BuildCondition(jsgraph()->NullConstant()); |
| 1348 BuildConditionalJump(condition); |
| 1244 } | 1349 } |
| 1245 | 1350 |
| 1246 | 1351 |
| 1247 void BytecodeGraphBuilder::VisitJumpIfUndefined( | 1352 void BytecodeGraphBuilder::VisitJumpIfUndefined( |
| 1248 const interpreter::BytecodeArrayIterator& iterator) { | 1353 const interpreter::BytecodeArrayIterator& iterator) { |
| 1249 UNIMPLEMENTED(); | 1354 Node* condition = BuildCondition(jsgraph()->UndefinedConstant()); |
| 1355 BuildConditionalJump(condition); |
| 1250 } | 1356 } |
| 1251 | 1357 |
| 1252 | 1358 |
| 1253 void BytecodeGraphBuilder::VisitJumpIfUndefinedConstant( | 1359 void BytecodeGraphBuilder::VisitJumpIfUndefinedConstant( |
| 1254 const interpreter::BytecodeArrayIterator& iterator) { | 1360 const interpreter::BytecodeArrayIterator& iterator) { |
| 1255 UNIMPLEMENTED(); | 1361 Node* condition = BuildCondition(jsgraph()->UndefinedConstant()); |
| 1362 BuildConditionalJump(condition); |
| 1256 } | 1363 } |
| 1257 | 1364 |
| 1258 | 1365 |
| 1259 void BytecodeGraphBuilder::VisitReturn( | 1366 void BytecodeGraphBuilder::VisitReturn( |
| 1260 const interpreter::BytecodeArrayIterator& iterator) { | 1367 const interpreter::BytecodeArrayIterator& iterator) { |
| 1261 Node* control = | 1368 Node* control = |
| 1262 NewNode(common()->Return(), environment()->LookupAccumulator()); | 1369 NewNode(common()->Return(), environment()->LookupAccumulator()); |
| 1263 UpdateControlDependencyToLeaveFunction(control); | 1370 UpdateControlDependencyToLeaveFunction(control); |
| 1371 set_environment(nullptr); |
| 1264 } | 1372 } |
| 1265 | 1373 |
| 1266 | 1374 |
| 1267 void BytecodeGraphBuilder::VisitForInPrepare( | 1375 void BytecodeGraphBuilder::VisitForInPrepare( |
| 1268 const interpreter::BytecodeArrayIterator& iterator) { | 1376 const interpreter::BytecodeArrayIterator& iterator) { |
| 1269 UNIMPLEMENTED(); | 1377 UNIMPLEMENTED(); |
| 1270 } | 1378 } |
| 1271 | 1379 |
| 1272 | 1380 |
| 1273 void BytecodeGraphBuilder::VisitForInNext( | 1381 void BytecodeGraphBuilder::VisitForInNext( |
| 1274 const interpreter::BytecodeArrayIterator& iterator) { | 1382 const interpreter::BytecodeArrayIterator& iterator) { |
| 1275 UNIMPLEMENTED(); | 1383 UNIMPLEMENTED(); |
| 1276 } | 1384 } |
| 1277 | 1385 |
| 1278 | 1386 |
| 1279 void BytecodeGraphBuilder::VisitForInDone( | 1387 void BytecodeGraphBuilder::VisitForInDone( |
| 1280 const interpreter::BytecodeArrayIterator& iterator) { | 1388 const interpreter::BytecodeArrayIterator& iterator) { |
| 1281 UNIMPLEMENTED(); | 1389 UNIMPLEMENTED(); |
| 1282 } | 1390 } |
| 1283 | 1391 |
| 1284 | 1392 |
| 1393 void BytecodeGraphBuilder::MergeEnvironmentsOfBackwardBranches( |
| 1394 int source_offset, int target_offset) { |
| 1395 DCHECK_GE(source_offset, target_offset); |
| 1396 const ZoneVector<int>* branch_sites = |
| 1397 branch_analysis()->BackwardBranchesTargetting(target_offset); |
| 1398 if (branch_sites->back() == source_offset) { |
| 1399 // The set of back branches is complete, merge them. |
| 1400 DCHECK_GE(branch_sites->at(0), target_offset); |
| 1401 Environment* merged = merge_environments_[branch_sites->at(0)]; |
| 1402 for (size_t i = 1; i < branch_sites->size(); i++) { |
| 1403 DCHECK_GE(branch_sites->at(i), target_offset); |
| 1404 merged->Merge(merge_environments_[branch_sites->at(i)]); |
| 1405 } |
| 1406 // And now merge with loop header environment created when loop |
| 1407 // header was visited. |
| 1408 loop_header_environments_[target_offset]->Merge(merged); |
| 1409 } |
| 1410 } |
| 1411 |
| 1412 |
| 1413 void BytecodeGraphBuilder::MergeEnvironmentsOfForwardBranches( |
| 1414 int source_offset) { |
| 1415 if (branch_analysis()->forward_branches_target(source_offset)) { |
| 1416 // Merge environments of branches that reach this bytecode. |
| 1417 auto branch_sites = |
| 1418 branch_analysis()->ForwardBranchesTargetting(source_offset); |
| 1419 DCHECK_LT(branch_sites->at(0), source_offset); |
| 1420 Environment* merged = merge_environments_[branch_sites->at(0)]; |
| 1421 for (size_t i = 1; i < branch_sites->size(); i++) { |
| 1422 DCHECK_LT(branch_sites->at(i), source_offset); |
| 1423 merged->Merge(merge_environments_[branch_sites->at(i)]); |
| 1424 } |
| 1425 if (environment()) { |
| 1426 merged->Merge(environment()); |
| 1427 } |
| 1428 set_environment(merged); |
| 1429 } |
| 1430 } |
| 1431 |
| 1432 |
| 1433 void BytecodeGraphBuilder::BuildLoopHeaderForBackwardBranches( |
| 1434 int source_offset) { |
| 1435 if (branch_analysis()->backward_branches_target(source_offset)) { |
| 1436 // Add loop header and store a copy so we can connect merged back |
| 1437 // edge inputs to the loop header. |
| 1438 loop_header_environments_[source_offset] = environment()->CopyForLoop(); |
| 1439 } |
| 1440 } |
| 1441 |
| 1442 |
| 1443 void BytecodeGraphBuilder::BuildJump(int source_offset, int target_offset) { |
| 1444 DCHECK_NULL(merge_environments_[source_offset]); |
| 1445 merge_environments_[source_offset] = environment(); |
| 1446 if (source_offset >= target_offset) { |
| 1447 MergeEnvironmentsOfBackwardBranches(source_offset, target_offset); |
| 1448 } |
| 1449 set_environment(nullptr); |
| 1450 } |
| 1451 |
| 1452 |
| 1453 void BytecodeGraphBuilder::BuildJump() { |
| 1454 int source_offset = bytecode_iterator()->current_offset(); |
| 1455 int target_offset = bytecode_iterator()->GetJumpTargetOffset(); |
| 1456 BuildJump(source_offset, target_offset); |
| 1457 } |
| 1458 |
| 1459 |
| 1460 void BytecodeGraphBuilder::BuildConditionalJump(Node* condition) { |
| 1461 int source_offset = bytecode_iterator()->current_offset(); |
| 1462 NewBranch(condition); |
| 1463 Environment* if_false_environment = environment()->CopyForConditional(); |
| 1464 NewIfTrue(); |
| 1465 BuildJump(source_offset, bytecode_iterator()->GetJumpTargetOffset()); |
| 1466 set_environment(if_false_environment); |
| 1467 NewIfFalse(); |
| 1468 } |
| 1469 |
| 1470 |
| 1471 Node* BytecodeGraphBuilder::BuildCondition(Node* comperand) { |
| 1472 Node* accumulator = environment()->LookupAccumulator(); |
| 1473 return NewNode(javascript()->StrictEqual(), accumulator, comperand); |
| 1474 } |
| 1475 |
| 1476 |
| 1477 Node* BytecodeGraphBuilder::BuildToBooleanCondition(Node* comperand) { |
| 1478 Node* accumulator = environment()->LookupAccumulator(); |
| 1479 Node* to_boolean = |
| 1480 NewNode(javascript()->ToBoolean(ToBooleanHint::kAny), accumulator); |
| 1481 return NewNode(javascript()->StrictEqual(), to_boolean, comperand); |
| 1482 } |
| 1483 |
| 1484 |
| 1285 Node** BytecodeGraphBuilder::EnsureInputBufferSize(int size) { | 1485 Node** BytecodeGraphBuilder::EnsureInputBufferSize(int size) { |
| 1286 if (size > input_buffer_size_) { | 1486 if (size > input_buffer_size_) { |
| 1287 size = size + kInputBufferSizeIncrement + input_buffer_size_; | 1487 size = size + kInputBufferSizeIncrement + input_buffer_size_; |
| 1288 input_buffer_ = local_zone()->NewArray<Node*>(size); | 1488 input_buffer_ = local_zone()->NewArray<Node*>(size); |
| 1289 input_buffer_size_ = size; | 1489 input_buffer_size_ = size; |
| 1290 } | 1490 } |
| 1291 return input_buffer_; | 1491 return input_buffer_; |
| 1292 } | 1492 } |
| 1293 | 1493 |
| 1294 | 1494 |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1347 Node* on_success = graph()->NewNode(if_success, result); | 1547 Node* on_success = graph()->NewNode(if_success, result); |
| 1348 environment_->UpdateControlDependency(on_success); | 1548 environment_->UpdateControlDependency(on_success); |
| 1349 } | 1549 } |
| 1350 } | 1550 } |
| 1351 } | 1551 } |
| 1352 | 1552 |
| 1353 return result; | 1553 return result; |
| 1354 } | 1554 } |
| 1355 | 1555 |
| 1356 | 1556 |
| 1557 Node* BytecodeGraphBuilder::NewPhi(int count, Node* input, Node* control) { |
| 1558 const Operator* phi_op = common()->Phi(MachineRepresentation::kTagged, count); |
| 1559 Node** buffer = EnsureInputBufferSize(count + 1); |
| 1560 MemsetPointer(buffer, input, count); |
| 1561 buffer[count] = control; |
| 1562 return graph()->NewNode(phi_op, count + 1, buffer, true); |
| 1563 } |
| 1564 |
| 1565 |
| 1566 Node* BytecodeGraphBuilder::NewEffectPhi(int count, Node* input, |
| 1567 Node* control) { |
| 1568 const Operator* phi_op = common()->EffectPhi(count); |
| 1569 Node** buffer = EnsureInputBufferSize(count + 1); |
| 1570 MemsetPointer(buffer, input, count); |
| 1571 buffer[count] = control; |
| 1572 return graph()->NewNode(phi_op, count + 1, buffer, true); |
| 1573 } |
| 1574 |
| 1575 |
| 1357 Node* BytecodeGraphBuilder::MergeControl(Node* control, Node* other) { | 1576 Node* BytecodeGraphBuilder::MergeControl(Node* control, Node* other) { |
| 1358 int inputs = control->op()->ControlInputCount() + 1; | 1577 int inputs = control->op()->ControlInputCount() + 1; |
| 1359 if (control->opcode() == IrOpcode::kLoop) { | 1578 if (control->opcode() == IrOpcode::kLoop) { |
| 1360 // Control node for loop exists, add input. | 1579 // Control node for loop exists, add input. |
| 1361 const Operator* op = common()->Loop(inputs); | 1580 const Operator* op = common()->Loop(inputs); |
| 1362 control->AppendInput(graph_zone(), other); | 1581 control->AppendInput(graph_zone(), other); |
| 1363 NodeProperties::ChangeOp(control, op); | 1582 NodeProperties::ChangeOp(control, op); |
| 1364 } else if (control->opcode() == IrOpcode::kMerge) { | 1583 } else if (control->opcode() == IrOpcode::kMerge) { |
| 1365 // Control node for merge exists, add input. | 1584 // Control node for merge exists, add input. |
| 1366 const Operator* op = common()->Merge(inputs); | 1585 const Operator* op = common()->Merge(inputs); |
| 1367 control->AppendInput(graph_zone(), other); | 1586 control->AppendInput(graph_zone(), other); |
| 1368 NodeProperties::ChangeOp(control, op); | 1587 NodeProperties::ChangeOp(control, op); |
| 1369 } else { | 1588 } else { |
| 1370 // Control node is a singleton, introduce a merge. | 1589 // Control node is a singleton, introduce a merge. |
| 1371 const Operator* op = common()->Merge(inputs); | 1590 const Operator* op = common()->Merge(inputs); |
| 1372 Node* merge_inputs[] = {control, other}; | 1591 Node* merge_inputs[] = {control, other}; |
| 1373 control = graph()->NewNode(op, arraysize(merge_inputs), merge_inputs, true); | 1592 control = graph()->NewNode(op, arraysize(merge_inputs), merge_inputs, true); |
| 1374 } | 1593 } |
| 1375 return control; | 1594 return control; |
| 1376 } | 1595 } |
| 1377 | 1596 |
| 1378 | 1597 |
| 1598 Node* BytecodeGraphBuilder::MergeEffect(Node* value, Node* other, |
| 1599 Node* control) { |
| 1600 int inputs = control->op()->ControlInputCount(); |
| 1601 if (value->opcode() == IrOpcode::kEffectPhi && |
| 1602 NodeProperties::GetControlInput(value) == control) { |
| 1603 // Phi already exists, add input. |
| 1604 value->InsertInput(graph_zone(), inputs - 1, other); |
| 1605 NodeProperties::ChangeOp(value, common()->EffectPhi(inputs)); |
| 1606 } else if (value != other) { |
| 1607 // Phi does not exist yet, introduce one. |
| 1608 value = NewEffectPhi(inputs, value, control); |
| 1609 value->ReplaceInput(inputs - 1, other); |
| 1610 } |
| 1611 return value; |
| 1612 } |
| 1613 |
| 1614 |
| 1615 Node* BytecodeGraphBuilder::MergeValue(Node* value, Node* other, |
| 1616 Node* control) { |
| 1617 int inputs = control->op()->ControlInputCount(); |
| 1618 if (value->opcode() == IrOpcode::kPhi && |
| 1619 NodeProperties::GetControlInput(value) == control) { |
| 1620 // Phi already exists, add input. |
| 1621 value->InsertInput(graph_zone(), inputs - 1, other); |
| 1622 NodeProperties::ChangeOp( |
| 1623 value, common()->Phi(MachineRepresentation::kTagged, inputs)); |
| 1624 } else if (value != other) { |
| 1625 // Phi does not exist yet, introduce one. |
| 1626 value = NewPhi(inputs, value, control); |
| 1627 value->ReplaceInput(inputs - 1, other); |
| 1628 } |
| 1629 return value; |
| 1630 } |
| 1631 |
| 1632 |
| 1379 void BytecodeGraphBuilder::UpdateControlDependencyToLeaveFunction(Node* exit) { | 1633 void BytecodeGraphBuilder::UpdateControlDependencyToLeaveFunction(Node* exit) { |
| 1380 if (environment()->IsMarkedAsUnreachable()) return; | 1634 if (environment()->IsMarkedAsUnreachable()) return; |
| 1381 environment()->MarkAsUnreachable(); | 1635 environment()->MarkAsUnreachable(); |
| 1382 exit_controls_.push_back(exit); | 1636 exit_controls_.push_back(exit); |
| 1383 } | 1637 } |
| 1384 | 1638 |
| 1385 } // namespace compiler | 1639 } // namespace compiler |
| 1386 } // namespace internal | 1640 } // namespace internal |
| 1387 } // namespace v8 | 1641 } // namespace v8 |
| OLD | NEW |