Chromium Code Reviews| 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 (int i = 0; i < static_cast<int>(values_.size()); i++) { | |
| 163 values_[i] = builder()->MergeValue(values_[i], other->values_[i], control); | |
| 164 } | |
| 165 } | |
| 166 | |
| 167 | |
| 168 void BytecodeGraphBuilder::Environment::PrepareForLoop() { | |
| 169 Node* control = builder()->NewLoop(); | |
| 170 accumulator_ = builder()->NewPhi(1, accumulator_, control); | |
| 171 context_ = builder()->NewPhi(1, context_, control); | |
| 172 | |
| 173 int size = static_cast<int>(values()->size()); | |
| 174 for (int i = 0; i < size; i++) { | |
| 175 values()->at(i) = builder()->NewPhi(1, values()->at(i), control); | |
| 176 } | |
| 177 Node* effect = builder_->NewEffectPhi(1, GetEffectDependency(), control); | |
| 178 UpdateEffectDependency(effect); | |
| 179 | |
| 180 Node* terminate = builder()->graph()->NewNode( | |
| 181 builder()->common()->Terminate(), effect, control); | |
| 182 builder()->exit_controls_.push_back(terminate); | |
| 183 } | |
| 184 | |
| 185 | |
| 110 BytecodeGraphBuilder::BytecodeGraphBuilder(Zone* local_zone, | 186 BytecodeGraphBuilder::BytecodeGraphBuilder(Zone* local_zone, |
| 111 CompilationInfo* compilation_info, | 187 CompilationInfo* compilation_info, |
| 112 JSGraph* jsgraph) | 188 JSGraph* jsgraph) |
| 113 : local_zone_(local_zone), | 189 : local_zone_(local_zone), |
| 114 info_(compilation_info), | 190 info_(compilation_info), |
| 115 jsgraph_(jsgraph), | 191 jsgraph_(jsgraph), |
| 192 merge_environments_(local_zone), | |
| 193 loop_header_environments_(local_zone), | |
| 116 input_buffer_size_(0), | 194 input_buffer_size_(0), |
| 117 input_buffer_(nullptr), | 195 input_buffer_(nullptr), |
| 118 exit_controls_(local_zone) { | 196 exit_controls_(local_zone) { |
| 119 bytecode_array_ = handle(info()->shared_info()->bytecode_array()); | 197 bytecode_array_ = handle(info()->shared_info()->bytecode_array()); |
| 120 } | 198 } |
| 121 | 199 |
| 122 | 200 |
| 123 Node* BytecodeGraphBuilder::GetNewTarget() { | 201 Node* BytecodeGraphBuilder::GetNewTarget() { |
| 124 if (!new_target_.is_set()) { | 202 if (!new_target_.is_set()) { |
| 125 int params = bytecode_array()->parameter_count(); | 203 int params = bytecode_array()->parameter_count(); |
| (...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 240 | 318 |
| 241 | 319 |
| 242 void BytecodeGraphBuilder::CreateGraphBody(bool stack_check) { | 320 void BytecodeGraphBuilder::CreateGraphBody(bool stack_check) { |
| 243 // TODO(oth): Review ast-graph-builder equivalent, i.e. arguments | 321 // TODO(oth): Review ast-graph-builder equivalent, i.e. arguments |
| 244 // object setup, this function variable if used, tracing hooks. | 322 // object setup, this function variable if used, tracing hooks. |
| 245 VisitBytecodes(); | 323 VisitBytecodes(); |
| 246 } | 324 } |
| 247 | 325 |
| 248 | 326 |
| 249 void BytecodeGraphBuilder::VisitBytecodes() { | 327 void BytecodeGraphBuilder::VisitBytecodes() { |
| 328 BytecodeBranchAnalysis analysis(bytecode_array(), local_zone()); | |
| 329 analysis.Analyze(); | |
| 330 set_branch_analysis(&analysis); | |
| 250 interpreter::BytecodeArrayIterator iterator(bytecode_array()); | 331 interpreter::BytecodeArrayIterator iterator(bytecode_array()); |
| 332 set_bytecode_iterator(&iterator); | |
| 251 while (!iterator.done()) { | 333 while (!iterator.done()) { |
| 252 switch (iterator.current_bytecode()) { | 334 if (analysis.is_reachable(iterator.current_offset())) { |
| 335 ApplyBranchAnalysis(&analysis); | |
| 336 | |
| 337 switch (iterator.current_bytecode()) { | |
| 253 #define BYTECODE_CASE(name, ...) \ | 338 #define BYTECODE_CASE(name, ...) \ |
| 254 case interpreter::Bytecode::k##name: \ | 339 case interpreter::Bytecode::k##name: \ |
| 255 Visit##name(iterator); \ | 340 Visit##name(iterator); \ |
| 256 break; | 341 break; |
| 257 BYTECODE_LIST(BYTECODE_CASE) | 342 BYTECODE_LIST(BYTECODE_CASE) |
| 258 #undef BYTECODE_CODE | 343 #undef BYTECODE_CODE |
| 344 } | |
| 259 } | 345 } |
| 260 iterator.Advance(); | 346 iterator.Advance(); |
| 261 } | 347 } |
| 348 set_branch_analysis(nullptr); | |
| 349 set_bytecode_iterator(nullptr); | |
| 262 } | 350 } |
| 263 | 351 |
| 264 | 352 |
| 265 void BytecodeGraphBuilder::VisitLdaZero( | 353 void BytecodeGraphBuilder::VisitLdaZero( |
| 266 const interpreter::BytecodeArrayIterator& iterator) { | 354 const interpreter::BytecodeArrayIterator& iterator) { |
| 267 Node* node = jsgraph()->ZeroConstant(); | 355 Node* node = jsgraph()->ZeroConstant(); |
| 268 environment()->BindAccumulator(node); | 356 environment()->BindAccumulator(node); |
| 269 } | 357 } |
| 270 | 358 |
| 271 | 359 |
| (...skipping 895 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1167 | 1255 |
| 1168 | 1256 |
| 1169 void BytecodeGraphBuilder::VisitToObject( | 1257 void BytecodeGraphBuilder::VisitToObject( |
| 1170 const interpreter::BytecodeArrayIterator& iterator) { | 1258 const interpreter::BytecodeArrayIterator& iterator) { |
| 1171 BuildCastOperator(javascript()->ToObject(), iterator); | 1259 BuildCastOperator(javascript()->ToObject(), iterator); |
| 1172 } | 1260 } |
| 1173 | 1261 |
| 1174 | 1262 |
| 1175 void BytecodeGraphBuilder::VisitJump( | 1263 void BytecodeGraphBuilder::VisitJump( |
| 1176 const interpreter::BytecodeArrayIterator& iterator) { | 1264 const interpreter::BytecodeArrayIterator& iterator) { |
| 1177 UNIMPLEMENTED(); | 1265 BuildJump(); |
| 1178 } | 1266 } |
| 1179 | 1267 |
| 1180 | 1268 |
| 1181 void BytecodeGraphBuilder::VisitJumpConstant( | 1269 void BytecodeGraphBuilder::VisitJumpConstant( |
| 1182 const interpreter::BytecodeArrayIterator& iterator) { | 1270 const interpreter::BytecodeArrayIterator& iterator) { |
| 1183 UNIMPLEMENTED(); | 1271 BuildJump(); |
| 1184 } | 1272 } |
| 1185 | 1273 |
| 1186 | 1274 |
| 1187 void BytecodeGraphBuilder::VisitJumpIfTrue( | 1275 void BytecodeGraphBuilder::VisitJumpIfTrue( |
| 1188 const interpreter::BytecodeArrayIterator& iterator) { | 1276 const interpreter::BytecodeArrayIterator& iterator) { |
| 1189 UNIMPLEMENTED(); | 1277 Node* condition = BuildJumpCondition(jsgraph()->TrueConstant()); |
| 1278 BuildConditionalJump(condition); | |
| 1190 } | 1279 } |
| 1191 | 1280 |
| 1192 | 1281 |
| 1193 void BytecodeGraphBuilder::VisitJumpIfTrueConstant( | 1282 void BytecodeGraphBuilder::VisitJumpIfTrueConstant( |
| 1194 const interpreter::BytecodeArrayIterator& iterator) { | 1283 const interpreter::BytecodeArrayIterator& iterator) { |
| 1195 UNIMPLEMENTED(); | 1284 Node* condition = BuildJumpCondition(jsgraph()->TrueConstant()); |
| 1285 BuildConditionalJump(condition); | |
| 1196 } | 1286 } |
| 1197 | 1287 |
| 1198 | 1288 |
| 1199 void BytecodeGraphBuilder::VisitJumpIfFalse( | 1289 void BytecodeGraphBuilder::VisitJumpIfFalse( |
| 1200 const interpreter::BytecodeArrayIterator& iterator) { | 1290 const interpreter::BytecodeArrayIterator& iterator) { |
| 1201 UNIMPLEMENTED(); | 1291 Node* condition = BuildJumpCondition(jsgraph()->FalseConstant()); |
| 1292 BuildConditionalJump(condition); | |
| 1202 } | 1293 } |
| 1203 | 1294 |
| 1204 | 1295 |
| 1205 void BytecodeGraphBuilder::VisitJumpIfFalseConstant( | 1296 void BytecodeGraphBuilder::VisitJumpIfFalseConstant( |
| 1206 const interpreter::BytecodeArrayIterator& iterator) { | 1297 const interpreter::BytecodeArrayIterator& iterator) { |
| 1207 UNIMPLEMENTED(); | 1298 Node* condition = BuildJumpCondition(jsgraph()->FalseConstant()); |
| 1299 BuildConditionalJump(condition); | |
| 1208 } | 1300 } |
| 1209 | 1301 |
| 1210 | 1302 |
| 1211 void BytecodeGraphBuilder::VisitJumpIfToBooleanTrue( | 1303 void BytecodeGraphBuilder::VisitJumpIfToBooleanTrue( |
| 1212 const interpreter::BytecodeArrayIterator& iterator) { | 1304 const interpreter::BytecodeArrayIterator& iterator) { |
| 1213 UNIMPLEMENTED(); | 1305 Node* condition = BuildToBooleanJumpCondition(jsgraph()->TrueConstant()); |
| 1306 BuildConditionalJump(condition); | |
| 1214 } | 1307 } |
| 1215 | 1308 |
| 1216 | 1309 |
| 1217 void BytecodeGraphBuilder::VisitJumpIfToBooleanTrueConstant( | 1310 void BytecodeGraphBuilder::VisitJumpIfToBooleanTrueConstant( |
| 1218 const interpreter::BytecodeArrayIterator& iterator) { | 1311 const interpreter::BytecodeArrayIterator& iterator) { |
| 1219 UNIMPLEMENTED(); | 1312 Node* condition = BuildToBooleanJumpCondition(jsgraph()->TrueConstant()); |
| 1313 BuildConditionalJump(condition); | |
| 1220 } | 1314 } |
| 1221 | 1315 |
| 1222 | 1316 |
| 1223 void BytecodeGraphBuilder::VisitJumpIfToBooleanFalse( | 1317 void BytecodeGraphBuilder::VisitJumpIfToBooleanFalse( |
| 1224 const interpreter::BytecodeArrayIterator& iterator) { | 1318 const interpreter::BytecodeArrayIterator& iterator) { |
| 1225 UNIMPLEMENTED(); | 1319 Node* condition = BuildToBooleanJumpCondition(jsgraph()->FalseConstant()); |
| 1320 BuildConditionalJump(condition); | |
| 1226 } | 1321 } |
| 1227 | 1322 |
| 1228 | 1323 |
| 1229 void BytecodeGraphBuilder::VisitJumpIfToBooleanFalseConstant( | 1324 void BytecodeGraphBuilder::VisitJumpIfToBooleanFalseConstant( |
| 1230 const interpreter::BytecodeArrayIterator& iterator) { | 1325 const interpreter::BytecodeArrayIterator& iterator) { |
| 1231 UNIMPLEMENTED(); | 1326 Node* condition = BuildToBooleanJumpCondition(jsgraph()->FalseConstant()); |
| 1327 BuildConditionalJump(condition); | |
| 1232 } | 1328 } |
| 1233 | 1329 |
| 1234 | 1330 |
| 1235 void BytecodeGraphBuilder::VisitJumpIfNull( | 1331 void BytecodeGraphBuilder::VisitJumpIfNull( |
| 1236 const interpreter::BytecodeArrayIterator& iterator) { | 1332 const interpreter::BytecodeArrayIterator& iterator) { |
| 1237 UNIMPLEMENTED(); | 1333 Node* condition = BuildJumpCondition(jsgraph()->NullConstant()); |
| 1334 BuildConditionalJump(condition); | |
| 1238 } | 1335 } |
| 1239 | 1336 |
| 1240 | 1337 |
| 1241 void BytecodeGraphBuilder::VisitJumpIfNullConstant( | 1338 void BytecodeGraphBuilder::VisitJumpIfNullConstant( |
| 1242 const interpreter::BytecodeArrayIterator& iterator) { | 1339 const interpreter::BytecodeArrayIterator& iterator) { |
| 1243 UNIMPLEMENTED(); | 1340 Node* condition = BuildJumpCondition(jsgraph()->NullConstant()); |
| 1341 BuildConditionalJump(condition); | |
| 1244 } | 1342 } |
| 1245 | 1343 |
| 1246 | 1344 |
| 1247 void BytecodeGraphBuilder::VisitJumpIfUndefined( | 1345 void BytecodeGraphBuilder::VisitJumpIfUndefined( |
| 1248 const interpreter::BytecodeArrayIterator& iterator) { | 1346 const interpreter::BytecodeArrayIterator& iterator) { |
| 1249 UNIMPLEMENTED(); | 1347 Node* condition = BuildJumpCondition(jsgraph()->UndefinedConstant()); |
| 1348 BuildConditionalJump(condition); | |
| 1250 } | 1349 } |
| 1251 | 1350 |
| 1252 | 1351 |
| 1253 void BytecodeGraphBuilder::VisitJumpIfUndefinedConstant( | 1352 void BytecodeGraphBuilder::VisitJumpIfUndefinedConstant( |
| 1254 const interpreter::BytecodeArrayIterator& iterator) { | 1353 const interpreter::BytecodeArrayIterator& iterator) { |
| 1255 UNIMPLEMENTED(); | 1354 Node* condition = BuildJumpCondition(jsgraph()->UndefinedConstant()); |
| 1355 BuildConditionalJump(condition); | |
| 1256 } | 1356 } |
| 1257 | 1357 |
| 1258 | 1358 |
| 1259 void BytecodeGraphBuilder::VisitReturn( | 1359 void BytecodeGraphBuilder::VisitReturn( |
| 1260 const interpreter::BytecodeArrayIterator& iterator) { | 1360 const interpreter::BytecodeArrayIterator& iterator) { |
| 1261 Node* control = | 1361 Node* control = |
| 1262 NewNode(common()->Return(), environment()->LookupAccumulator()); | 1362 NewNode(common()->Return(), environment()->LookupAccumulator()); |
| 1263 UpdateControlDependencyToLeaveFunction(control); | 1363 UpdateControlDependencyToLeaveFunction(control); |
| 1364 set_environment(nullptr); | |
| 1264 } | 1365 } |
| 1265 | 1366 |
| 1266 | 1367 |
| 1267 void BytecodeGraphBuilder::VisitForInPrepare( | 1368 void BytecodeGraphBuilder::VisitForInPrepare( |
| 1268 const interpreter::BytecodeArrayIterator& iterator) { | 1369 const interpreter::BytecodeArrayIterator& iterator) { |
| 1269 UNIMPLEMENTED(); | 1370 UNIMPLEMENTED(); |
| 1270 } | 1371 } |
| 1271 | 1372 |
| 1272 | 1373 |
| 1273 void BytecodeGraphBuilder::VisitForInNext( | 1374 void BytecodeGraphBuilder::VisitForInNext( |
| 1274 const interpreter::BytecodeArrayIterator& iterator) { | 1375 const interpreter::BytecodeArrayIterator& iterator) { |
| 1275 UNIMPLEMENTED(); | 1376 UNIMPLEMENTED(); |
| 1276 } | 1377 } |
| 1277 | 1378 |
| 1278 | 1379 |
| 1279 void BytecodeGraphBuilder::VisitForInDone( | 1380 void BytecodeGraphBuilder::VisitForInDone( |
| 1280 const interpreter::BytecodeArrayIterator& iterator) { | 1381 const interpreter::BytecodeArrayIterator& iterator) { |
| 1281 UNIMPLEMENTED(); | 1382 UNIMPLEMENTED(); |
| 1282 } | 1383 } |
| 1283 | 1384 |
| 1284 | 1385 |
| 1386 void BytecodeGraphBuilder::ApplyBranchAnalysis( | |
|
rmcilroy
2015/12/15 17:35:43
Not keen on the name. How about MergeEnvironmentWi
oth
2015/12/15 22:42:17
Done.
| |
| 1387 const BytecodeBranchAnalysis* analysis) { | |
| 1388 int current_offset = bytecode_iterator()->current_offset(); | |
| 1389 if (analysis->forward_branches_target(current_offset)) { | |
| 1390 // Merge environments of branches that reach this bytecode. | |
| 1391 auto branch_sites = analysis->ForwardBranchesTargetting(current_offset); | |
| 1392 Environment* merged = merge_environments_[branch_sites->at(0)]; | |
| 1393 for (size_t i = 1; i < branch_sites->size(); i++) { | |
| 1394 DCHECK_LT(branch_sites->at(i), current_offset); | |
| 1395 merged->Merge(merge_environments_[branch_sites->at(i)]); | |
| 1396 } | |
| 1397 if (environment()) { | |
| 1398 merged->Merge(environment()); | |
| 1399 set_environment(nullptr); | |
|
rmcilroy
2015/12/15 17:35:43
why set nullptr here and set to merged immediately
oth
2015/12/15 22:42:17
Churn, removed.
| |
| 1400 } | |
| 1401 set_environment(merged); | |
| 1402 } | |
| 1403 | |
| 1404 if (analysis->backward_branches_target(current_offset)) { | |
| 1405 // Add loop header and store a copy so we can connect merged back | |
| 1406 // edge inputs to the loop header. | |
| 1407 loop_header_environments_[current_offset] = environment()->CopyForLoop(); | |
| 1408 } | |
| 1409 } | |
| 1410 | |
| 1411 | |
| 1412 void BytecodeGraphBuilder::BuildJump(int source_offset, int target_offset) { | |
| 1413 DCHECK_NULL(merge_environments_[source_offset]); | |
| 1414 merge_environments_[source_offset] = environment(); | |
| 1415 if (source_offset >= target_offset) { | |
| 1416 // Back branch check if all branches to target offset are | |
| 1417 // satisfied. | |
| 1418 const ZoneVector<int>* back_branches = | |
| 1419 branch_analysis()->BackwardBranchesTargetting(target_offset); | |
| 1420 if (back_branches->back() == source_offset) { | |
|
rmcilroy
2015/12/15 17:35:43
Use IsLastBackwardBranchTo here (or remove that fu
oth
2015/12/15 22:42:17
Removed it, want the branches immediately if true.
| |
| 1421 // The set of back branches is complete, merge them. | |
| 1422 Environment* environment = merge_environments_[back_branches->at(0)]; | |
| 1423 for (size_t i = 1; i < back_branches->size(); i++) { | |
| 1424 environment->Merge(merge_environments_[back_branches->at(i)]); | |
| 1425 } | |
| 1426 // And now merge with loop header environment created when loop | |
| 1427 // header was visited. | |
| 1428 loop_header_environments_[target_offset]->Merge(environment); | |
|
rmcilroy
2015/12/15 17:35:43
nit - could we pull the back-branch stuff out into
oth
2015/12/15 22:42:17
Done.
| |
| 1429 } | |
| 1430 } | |
| 1431 set_environment(nullptr); | |
| 1432 } | |
| 1433 | |
| 1434 | |
| 1435 void BytecodeGraphBuilder::BuildJump() { | |
| 1436 int source_offset = bytecode_iterator()->current_offset(); | |
| 1437 int target_offset = bytecode_iterator()->GetJumpTargetOffset(); | |
| 1438 BuildJump(source_offset, target_offset); | |
| 1439 } | |
| 1440 | |
| 1441 | |
| 1442 void BytecodeGraphBuilder::BuildConditionalJump(Node* condition) { | |
| 1443 int source_offset = bytecode_iterator()->current_offset(); | |
| 1444 NewBranch(condition); | |
| 1445 Environment* if_false_environment = environment()->CopyForConditional(); | |
| 1446 NewIfTrue(); | |
| 1447 BuildJump(source_offset, bytecode_iterator()->GetJumpTargetOffset()); | |
| 1448 set_environment(if_false_environment); | |
| 1449 NewIfFalse(); | |
| 1450 } | |
| 1451 | |
| 1452 | |
| 1453 Node* BytecodeGraphBuilder::BuildJumpCondition(Node* comperand) { | |
| 1454 Node* accumulator = environment()->LookupAccumulator(); | |
| 1455 return NewNode(javascript()->StrictEqual(), accumulator, comperand); | |
| 1456 } | |
| 1457 | |
| 1458 | |
| 1459 Node* BytecodeGraphBuilder::BuildToBooleanJumpCondition(Node* comperand) { | |
| 1460 Node* accumulator = environment()->LookupAccumulator(); | |
| 1461 Node* to_boolean = | |
| 1462 NewNode(javascript()->ToBoolean(ToBooleanHint::kAny), accumulator); | |
| 1463 return NewNode(javascript()->StrictEqual(), to_boolean, comperand); | |
| 1464 } | |
| 1465 | |
| 1466 | |
| 1285 Node** BytecodeGraphBuilder::EnsureInputBufferSize(int size) { | 1467 Node** BytecodeGraphBuilder::EnsureInputBufferSize(int size) { |
| 1286 if (size > input_buffer_size_) { | 1468 if (size > input_buffer_size_) { |
| 1287 size = size + kInputBufferSizeIncrement + input_buffer_size_; | 1469 size = size + kInputBufferSizeIncrement + input_buffer_size_; |
| 1288 input_buffer_ = local_zone()->NewArray<Node*>(size); | 1470 input_buffer_ = local_zone()->NewArray<Node*>(size); |
| 1289 input_buffer_size_ = size; | 1471 input_buffer_size_ = size; |
| 1290 } | 1472 } |
| 1291 return input_buffer_; | 1473 return input_buffer_; |
| 1292 } | 1474 } |
| 1293 | 1475 |
| 1294 | 1476 |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1347 Node* on_success = graph()->NewNode(if_success, result); | 1529 Node* on_success = graph()->NewNode(if_success, result); |
| 1348 environment_->UpdateControlDependency(on_success); | 1530 environment_->UpdateControlDependency(on_success); |
| 1349 } | 1531 } |
| 1350 } | 1532 } |
| 1351 } | 1533 } |
| 1352 | 1534 |
| 1353 return result; | 1535 return result; |
| 1354 } | 1536 } |
| 1355 | 1537 |
| 1356 | 1538 |
| 1539 Node* BytecodeGraphBuilder::NewPhi(int count, Node* input, Node* control) { | |
| 1540 const Operator* phi_op = common()->Phi(MachineRepresentation::kTagged, count); | |
| 1541 Node** buffer = EnsureInputBufferSize(count + 1); | |
| 1542 MemsetPointer(buffer, input, count); | |
| 1543 buffer[count] = control; | |
| 1544 return graph()->NewNode(phi_op, count + 1, buffer, true); | |
| 1545 } | |
| 1546 | |
| 1547 | |
| 1548 // TODO(mstarzinger): Revisit this once we have proper effect states. | |
| 1549 Node* BytecodeGraphBuilder::NewEffectPhi(int count, Node* input, | |
| 1550 Node* control) { | |
| 1551 const Operator* phi_op = common()->EffectPhi(count); | |
| 1552 Node** buffer = EnsureInputBufferSize(count + 1); | |
| 1553 MemsetPointer(buffer, input, count); | |
| 1554 buffer[count] = control; | |
| 1555 return graph()->NewNode(phi_op, count + 1, buffer, true); | |
| 1556 } | |
| 1557 | |
| 1558 | |
| 1357 Node* BytecodeGraphBuilder::MergeControl(Node* control, Node* other) { | 1559 Node* BytecodeGraphBuilder::MergeControl(Node* control, Node* other) { |
| 1358 int inputs = control->op()->ControlInputCount() + 1; | 1560 int inputs = control->op()->ControlInputCount() + 1; |
| 1359 if (control->opcode() == IrOpcode::kLoop) { | 1561 if (control->opcode() == IrOpcode::kLoop) { |
| 1360 // Control node for loop exists, add input. | 1562 // Control node for loop exists, add input. |
| 1361 const Operator* op = common()->Loop(inputs); | 1563 const Operator* op = common()->Loop(inputs); |
| 1362 control->AppendInput(graph_zone(), other); | 1564 control->AppendInput(graph_zone(), other); |
| 1363 NodeProperties::ChangeOp(control, op); | 1565 NodeProperties::ChangeOp(control, op); |
| 1364 } else if (control->opcode() == IrOpcode::kMerge) { | 1566 } else if (control->opcode() == IrOpcode::kMerge) { |
| 1365 // Control node for merge exists, add input. | 1567 // Control node for merge exists, add input. |
| 1366 const Operator* op = common()->Merge(inputs); | 1568 const Operator* op = common()->Merge(inputs); |
| 1367 control->AppendInput(graph_zone(), other); | 1569 control->AppendInput(graph_zone(), other); |
| 1368 NodeProperties::ChangeOp(control, op); | 1570 NodeProperties::ChangeOp(control, op); |
| 1369 } else { | 1571 } else { |
| 1370 // Control node is a singleton, introduce a merge. | 1572 // Control node is a singleton, introduce a merge. |
| 1371 const Operator* op = common()->Merge(inputs); | 1573 const Operator* op = common()->Merge(inputs); |
| 1372 Node* merge_inputs[] = {control, other}; | 1574 Node* merge_inputs[] = {control, other}; |
| 1373 control = graph()->NewNode(op, arraysize(merge_inputs), merge_inputs, true); | 1575 control = graph()->NewNode(op, arraysize(merge_inputs), merge_inputs, true); |
| 1374 } | 1576 } |
| 1375 return control; | 1577 return control; |
| 1376 } | 1578 } |
| 1377 | 1579 |
| 1378 | 1580 |
| 1581 Node* BytecodeGraphBuilder::MergeEffect(Node* value, Node* other, | |
| 1582 Node* control) { | |
| 1583 int inputs = control->op()->ControlInputCount(); | |
| 1584 if (value->opcode() == IrOpcode::kEffectPhi && | |
| 1585 NodeProperties::GetControlInput(value) == control) { | |
| 1586 // Phi already exists, add input. | |
| 1587 value->InsertInput(graph_zone(), inputs - 1, other); | |
| 1588 NodeProperties::ChangeOp(value, common()->EffectPhi(inputs)); | |
| 1589 } else if (value != other) { | |
| 1590 // Phi does not exist yet, introduce one. | |
| 1591 value = NewEffectPhi(inputs, value, control); | |
| 1592 value->ReplaceInput(inputs - 1, other); | |
| 1593 } | |
| 1594 return value; | |
| 1595 } | |
| 1596 | |
| 1597 | |
| 1598 Node* BytecodeGraphBuilder::MergeValue(Node* value, Node* other, | |
| 1599 Node* control) { | |
| 1600 int inputs = control->op()->ControlInputCount(); | |
| 1601 if (value->opcode() == IrOpcode::kPhi && | |
| 1602 NodeProperties::GetControlInput(value) == control) { | |
| 1603 // Phi already exists, add input. | |
| 1604 value->InsertInput(graph_zone(), inputs - 1, other); | |
| 1605 NodeProperties::ChangeOp( | |
| 1606 value, common()->Phi(MachineRepresentation::kTagged, inputs)); | |
| 1607 } else if (value != other) { | |
| 1608 // Phi does not exist yet, introduce one. | |
| 1609 value = NewPhi(inputs, value, control); | |
| 1610 | |
| 1611 value->ReplaceInput(inputs - 1, other); | |
| 1612 } | |
| 1613 return value; | |
| 1614 } | |
| 1615 | |
| 1616 | |
| 1379 void BytecodeGraphBuilder::UpdateControlDependencyToLeaveFunction(Node* exit) { | 1617 void BytecodeGraphBuilder::UpdateControlDependencyToLeaveFunction(Node* exit) { |
| 1380 if (environment()->IsMarkedAsUnreachable()) return; | 1618 if (environment()->IsMarkedAsUnreachable()) return; |
| 1381 environment()->MarkAsUnreachable(); | 1619 environment()->MarkAsUnreachable(); |
| 1382 exit_controls_.push_back(exit); | 1620 exit_controls_.push_back(exit); |
| 1383 } | 1621 } |
| 1384 | 1622 |
| 1385 } // namespace compiler | 1623 } // namespace compiler |
| 1386 } // namespace internal | 1624 } // namespace internal |
| 1387 } // namespace v8 | 1625 } // namespace v8 |
| OLD | NEW |