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 |