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-basic-block-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/bytecode-array-iterator.h" |
| 10 #include "src/interpreter/bytecodes.h" | 11 #include "src/interpreter/bytecodes.h" |
| 11 | 12 |
| 12 namespace v8 { | 13 namespace v8 { |
| 13 namespace internal { | 14 namespace internal { |
| 14 namespace compiler { | 15 namespace compiler { |
| 15 | 16 |
| 16 // Issues: | 17 // Issues: |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 48 // Registers | 49 // Registers |
| 49 register_base_ = static_cast<int>(values()->size()); | 50 register_base_ = static_cast<int>(values()->size()); |
| 50 Node* undefined_constant = builder->jsgraph()->UndefinedConstant(); | 51 Node* undefined_constant = builder->jsgraph()->UndefinedConstant(); |
| 51 values()->insert(values()->end(), register_count, undefined_constant); | 52 values()->insert(values()->end(), register_count, undefined_constant); |
| 52 | 53 |
| 53 // Accumulator | 54 // Accumulator |
| 54 accumulator_ = undefined_constant; | 55 accumulator_ = undefined_constant; |
| 55 } | 56 } |
| 56 | 57 |
| 57 | 58 |
| 59 BytecodeGraphBuilder::Environment::Environment( | |
| 60 const BytecodeGraphBuilder::Environment* other) | |
| 61 : builder_(other->builder_), | |
| 62 register_count_(other->register_count_), | |
| 63 parameter_count_(other->parameter_count_), | |
| 64 accumulator_(other->accumulator_), | |
| 65 context_(other->context_), | |
| 66 control_dependency_(other->control_dependency_), | |
| 67 effect_dependency_(other->effect_dependency_), | |
| 68 values_(other->zone()), | |
| 69 register_base_(other->register_base_) { | |
| 70 values_ = other->values_; | |
| 71 } | |
| 72 | |
| 73 | |
| 58 int BytecodeGraphBuilder::Environment::RegisterToValuesIndex( | 74 int BytecodeGraphBuilder::Environment::RegisterToValuesIndex( |
| 59 interpreter::Register the_register) const { | 75 interpreter::Register the_register) const { |
| 60 if (the_register.is_parameter()) { | 76 if (the_register.is_parameter()) { |
| 61 return the_register.ToParameterIndex(parameter_count()); | 77 return the_register.ToParameterIndex(parameter_count()); |
| 62 } else { | 78 } else { |
| 63 return the_register.index() + register_base(); | 79 return the_register.index() + register_base(); |
| 64 } | 80 } |
| 65 } | 81 } |
| 66 | 82 |
| 67 | 83 |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 100 bool BytecodeGraphBuilder::Environment::IsMarkedAsUnreachable() const { | 116 bool BytecodeGraphBuilder::Environment::IsMarkedAsUnreachable() const { |
| 101 return GetControlDependency()->opcode() == IrOpcode::kDead; | 117 return GetControlDependency()->opcode() == IrOpcode::kDead; |
| 102 } | 118 } |
| 103 | 119 |
| 104 | 120 |
| 105 void BytecodeGraphBuilder::Environment::MarkAsUnreachable() { | 121 void BytecodeGraphBuilder::Environment::MarkAsUnreachable() { |
| 106 UpdateControlDependency(builder()->jsgraph()->Dead()); | 122 UpdateControlDependency(builder()->jsgraph()->Dead()); |
| 107 } | 123 } |
| 108 | 124 |
| 109 | 125 |
| 126 BytecodeGraphBuilder::Environment* | |
| 127 BytecodeGraphBuilder::Environment::CopyForLoop() { | |
| 128 PrepareForLoop(); | |
| 129 return new (zone()) Environment(this); | |
| 130 } | |
| 131 | |
| 132 | |
| 133 BytecodeGraphBuilder::Environment* | |
| 134 BytecodeGraphBuilder::Environment::CopyForConditional() const { | |
| 135 return new (zone()) Environment(this); | |
| 136 } | |
| 137 | |
| 138 | |
| 139 void BytecodeGraphBuilder::Environment::Merge( | |
| 140 BytecodeGraphBuilder::Environment* other) { | |
| 141 // Nothing to do if the other environment is dead. | |
| 142 if (other->IsMarkedAsUnreachable()) { | |
| 143 return; | |
| 144 } | |
| 145 | |
| 146 // Create a merge of the control dependencies of both environments and update | |
| 147 // the current environment's control dependency accordingly. | |
| 148 Node* control = builder()->MergeControl(GetControlDependency(), | |
| 149 other->GetControlDependency()); | |
| 150 UpdateControlDependency(control); | |
| 151 | |
| 152 // Create a merge of the effect dependencies of both environments and update | |
| 153 // the current environment's effect dependency accordingly. | |
| 154 Node* effect = builder()->MergeEffect(GetEffectDependency(), | |
| 155 other->GetEffectDependency(), control); | |
| 156 UpdateEffectDependency(effect); | |
| 157 | |
| 158 // Introduce Phi nodes for values that have differing input at merge points, | |
| 159 // potentially extending an existing Phi node if possible. | |
| 160 accumulator_ = | |
| 161 builder()->MergeValue(accumulator_, other->accumulator_, control); | |
| 162 context_ = builder()->MergeValue(context_, other->context_, control); | |
| 163 for (int i = 0; i < static_cast<int>(values_.size()); i++) { | |
| 164 values_[i] = builder()->MergeValue(values_[i], other->values_[i], control); | |
| 165 } | |
| 166 } | |
| 167 | |
| 168 | |
| 169 void BytecodeGraphBuilder::Environment::PrepareForLoop() { | |
| 170 Node* control = builder()->NewLoop(); | |
| 171 accumulator_ = builder()->NewPhi(1, accumulator_, control); | |
| 172 context_ = builder()->NewPhi(1, context_, control); | |
| 173 | |
| 174 int size = static_cast<int>(values()->size()); | |
| 175 for (int i = 0; i < size; i++) { | |
| 176 values()->at(i) = builder()->NewPhi(1, values()->at(i), control); | |
| 177 } | |
| 178 Node* effect = builder_->NewEffectPhi(1, GetEffectDependency(), control); | |
| 179 UpdateEffectDependency(effect); | |
| 180 | |
| 181 Node* terminate = builder()->graph()->NewNode( | |
| 182 builder()->common()->Terminate(), effect, control); | |
| 183 builder()->exit_controls_.push_back(terminate); | |
| 184 } | |
| 185 | |
| 186 | |
| 110 BytecodeGraphBuilder::BytecodeGraphBuilder(Zone* local_zone, | 187 BytecodeGraphBuilder::BytecodeGraphBuilder(Zone* local_zone, |
| 111 CompilationInfo* compilation_info, | 188 CompilationInfo* compilation_info, |
| 112 JSGraph* jsgraph) | 189 JSGraph* jsgraph) |
| 113 : local_zone_(local_zone), | 190 : local_zone_(local_zone), |
| 114 info_(compilation_info), | 191 info_(compilation_info), |
| 115 jsgraph_(jsgraph), | 192 jsgraph_(jsgraph), |
| 193 block_environment_infos_(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 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 234 Node* end = graph()->NewNode(common()->End(input_count), input_count, inputs); | 312 Node* end = graph()->NewNode(common()->End(input_count), input_count, inputs); |
| 235 graph()->SetEnd(end); | 313 graph()->SetEnd(end); |
| 236 | 314 |
| 237 return true; | 315 return true; |
| 238 } | 316 } |
| 239 | 317 |
| 240 | 318 |
| 241 void BytecodeGraphBuilder::CreateGraphBody(bool stack_check) { | 319 void BytecodeGraphBuilder::CreateGraphBody(bool stack_check) { |
| 242 // TODO(oth): Review ast-graph-builder equivalent, i.e. arguments | 320 // TODO(oth): Review ast-graph-builder equivalent, i.e. arguments |
| 243 // object setup, this function variable if used, tracing hooks. | 321 // object setup, this function variable if used, tracing hooks. |
| 244 VisitBytecodes(); | 322 VisitBasicBlocks(); |
| 245 } | 323 } |
| 246 | 324 |
| 247 | 325 |
| 248 void BytecodeGraphBuilder::VisitBytecodes() { | 326 void BytecodeGraphBuilder::VisitBasicBlocks() { |
| 327 BytecodeBasicBlockAnalysis analyzer(local_zone(), bytecode_array()); | |
| 328 const ZoneVector<BytecodeBasicBlock*>* blocks = analyzer.Analyze(); | |
| 329 | |
| 330 block_environment_infos_.resize(blocks->size()); | |
| 331 for (auto block_iter = blocks->begin(); block_iter != blocks->end(); | |
| 332 block_iter++) { | |
| 333 VisitBytecodesInBasicBlock(*block_iter); | |
| 334 } | |
| 335 } | |
| 336 | |
| 337 void BytecodeGraphBuilder::VisitBytecodesInBasicBlock( | |
| 338 BytecodeBasicBlock* block) { | |
| 339 set_basic_block(block); | |
| 340 PrepareForNewBasicBlockVisit(); | |
| 341 | |
| 249 interpreter::BytecodeArrayIterator iterator(bytecode_array()); | 342 interpreter::BytecodeArrayIterator iterator(bytecode_array()); |
| 250 while (!iterator.done()) { | 343 iterator.AdvanceToOffset(basic_block()->start()); |
| 344 while (!iterator.done() && | |
| 345 iterator.current_offset() != basic_block()->end()) { | |
| 251 switch (iterator.current_bytecode()) { | 346 switch (iterator.current_bytecode()) { |
| 252 #define BYTECODE_CASE(name, ...) \ | 347 #define BYTECODE_CASE(name, ...) \ |
| 253 case interpreter::Bytecode::k##name: \ | 348 case interpreter::Bytecode::k##name: \ |
| 254 Visit##name(iterator); \ | 349 Visit##name(iterator); \ |
| 255 break; | 350 break; |
| 256 BYTECODE_LIST(BYTECODE_CASE) | 351 BYTECODE_LIST(BYTECODE_CASE) |
| 257 #undef BYTECODE_CODE | 352 #undef BYTECODE_CODE |
| 258 } | 353 } |
| 259 iterator.Advance(); | 354 iterator.Advance(); |
| 260 } | 355 } |
| 356 CompleteNewBasicBlockVisit(); | |
| 261 } | 357 } |
| 262 | 358 |
| 263 | 359 |
| 264 void BytecodeGraphBuilder::VisitLdaZero( | 360 void BytecodeGraphBuilder::VisitLdaZero( |
| 265 const interpreter::BytecodeArrayIterator& iterator) { | 361 const interpreter::BytecodeArrayIterator& iterator) { |
| 266 Node* node = jsgraph()->ZeroConstant(); | 362 Node* node = jsgraph()->ZeroConstant(); |
| 267 environment()->BindAccumulator(node); | 363 environment()->BindAccumulator(node); |
| 268 } | 364 } |
| 269 | 365 |
| 270 | 366 |
| (...skipping 840 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1111 | 1207 |
| 1112 | 1208 |
| 1113 void BytecodeGraphBuilder::VisitToObject( | 1209 void BytecodeGraphBuilder::VisitToObject( |
| 1114 const interpreter::BytecodeArrayIterator& iterator) { | 1210 const interpreter::BytecodeArrayIterator& iterator) { |
| 1115 BuildCastOperator(javascript()->ToObject(), iterator); | 1211 BuildCastOperator(javascript()->ToObject(), iterator); |
| 1116 } | 1212 } |
| 1117 | 1213 |
| 1118 | 1214 |
| 1119 void BytecodeGraphBuilder::VisitJump( | 1215 void BytecodeGraphBuilder::VisitJump( |
| 1120 const interpreter::BytecodeArrayIterator& iterator) { | 1216 const interpreter::BytecodeArrayIterator& iterator) { |
| 1121 UNIMPLEMENTED(); | 1217 BuildJump(); |
| 1122 } | 1218 } |
| 1123 | 1219 |
| 1124 | 1220 |
| 1125 void BytecodeGraphBuilder::VisitJumpConstant( | 1221 void BytecodeGraphBuilder::VisitJumpConstant( |
| 1126 const interpreter::BytecodeArrayIterator& iterator) { | 1222 const interpreter::BytecodeArrayIterator& iterator) { |
| 1127 UNIMPLEMENTED(); | 1223 BuildJump(); |
| 1128 } | 1224 } |
| 1129 | 1225 |
| 1130 | 1226 |
| 1131 void BytecodeGraphBuilder::VisitJumpIfTrue( | 1227 void BytecodeGraphBuilder::VisitJumpIfTrue( |
| 1132 const interpreter::BytecodeArrayIterator& iterator) { | 1228 const interpreter::BytecodeArrayIterator& iterator) { |
| 1133 UNIMPLEMENTED(); | 1229 Node* accumulator = environment()->LookupAccumulator(); |
| 1230 Node* comperand = jsgraph()->TrueConstant(); | |
| 1231 Node* comparison = | |
| 1232 NewNode(javascript()->StrictEqual(), accumulator, comperand); | |
| 1233 BuildConditionalJump(comparison); | |
| 1134 } | 1234 } |
| 1135 | 1235 |
| 1136 | 1236 |
| 1137 void BytecodeGraphBuilder::VisitJumpIfTrueConstant( | 1237 void BytecodeGraphBuilder::VisitJumpIfTrueConstant( |
| 1138 const interpreter::BytecodeArrayIterator& iterator) { | 1238 const interpreter::BytecodeArrayIterator& iterator) { |
| 1139 UNIMPLEMENTED(); | 1239 Node* accumulator = environment()->LookupAccumulator(); |
| 1240 Node* comperand = jsgraph()->TrueConstant(); | |
| 1241 Node* comparison = | |
| 1242 NewNode(javascript()->StrictEqual(), accumulator, comperand); | |
| 1243 BuildConditionalJump(comparison); | |
|
rmcilroy
2015/12/08 13:25:07
Please factor out the common code here into a Buil
oth
2015/12/09 11:26:45
I'd like to keep the control flow aspects and cond
| |
| 1140 } | 1244 } |
| 1141 | 1245 |
| 1142 | 1246 |
| 1143 void BytecodeGraphBuilder::VisitJumpIfFalse( | 1247 void BytecodeGraphBuilder::VisitJumpIfFalse( |
| 1144 const interpreter::BytecodeArrayIterator& iterator) { | 1248 const interpreter::BytecodeArrayIterator& iterator) { |
| 1145 UNIMPLEMENTED(); | 1249 Node* accumulator = environment()->LookupAccumulator(); |
| 1250 Node* comperand = jsgraph()->FalseConstant(); | |
| 1251 Node* comparison = | |
| 1252 NewNode(javascript()->StrictEqual(), accumulator, comperand); | |
| 1253 BuildConditionalJump(comparison); | |
| 1146 } | 1254 } |
| 1147 | 1255 |
| 1148 | 1256 |
| 1149 void BytecodeGraphBuilder::VisitJumpIfFalseConstant( | 1257 void BytecodeGraphBuilder::VisitJumpIfFalseConstant( |
| 1150 const interpreter::BytecodeArrayIterator& iterator) { | 1258 const interpreter::BytecodeArrayIterator& iterator) { |
| 1151 UNIMPLEMENTED(); | 1259 Node* accumulator = environment()->LookupAccumulator(); |
| 1260 Node* comperand = jsgraph()->FalseConstant(); | |
| 1261 Node* comparison = | |
| 1262 NewNode(javascript()->StrictEqual(), accumulator, comperand); | |
| 1263 BuildConditionalJump(comparison); | |
| 1152 } | 1264 } |
| 1153 | 1265 |
| 1154 | 1266 |
| 1155 void BytecodeGraphBuilder::VisitJumpIfToBooleanTrue( | 1267 void BytecodeGraphBuilder::VisitJumpIfToBooleanTrue( |
| 1156 const interpreter::BytecodeArrayIterator& iterator) { | 1268 const interpreter::BytecodeArrayIterator& iterator) { |
| 1157 UNIMPLEMENTED(); | 1269 Node* accumulator = environment()->LookupAccumulator(); |
| 1270 Node* to_boolean = | |
| 1271 NewNode(javascript()->ToBoolean(ToBooleanHint::kAny), accumulator); | |
| 1272 Node* comperand = jsgraph()->TrueConstant(); | |
| 1273 Node* comparison = | |
| 1274 NewNode(javascript()->StrictEqual(), to_boolean, comperand); | |
| 1275 BuildConditionalJump(comparison); | |
|
rmcilroy
2015/12/08 13:25:07
ditto, with a BuildJumpIfToBooleanValueEquals(...)
oth
2015/12/09 11:26:45
Done.
| |
| 1158 } | 1276 } |
| 1159 | 1277 |
| 1160 | 1278 |
| 1161 void BytecodeGraphBuilder::VisitJumpIfToBooleanTrueConstant( | 1279 void BytecodeGraphBuilder::VisitJumpIfToBooleanTrueConstant( |
| 1162 const interpreter::BytecodeArrayIterator& iterator) { | 1280 const interpreter::BytecodeArrayIterator& iterator) { |
| 1163 UNIMPLEMENTED(); | 1281 Node* accumulator = environment()->LookupAccumulator(); |
| 1282 Node* to_boolean = | |
| 1283 NewNode(javascript()->ToBoolean(ToBooleanHint::kAny), accumulator); | |
| 1284 Node* comperand = jsgraph()->TrueConstant(); | |
| 1285 Node* comparison = | |
| 1286 NewNode(javascript()->StrictEqual(), to_boolean, comperand); | |
| 1287 BuildConditionalJump(comparison); | |
| 1164 } | 1288 } |
| 1165 | 1289 |
| 1166 | 1290 |
| 1167 void BytecodeGraphBuilder::VisitJumpIfToBooleanFalse( | 1291 void BytecodeGraphBuilder::VisitJumpIfToBooleanFalse( |
| 1168 const interpreter::BytecodeArrayIterator& iterator) { | 1292 const interpreter::BytecodeArrayIterator& iterator) { |
| 1169 UNIMPLEMENTED(); | 1293 Node* accumulator = environment()->LookupAccumulator(); |
| 1294 Node* to_boolean = | |
| 1295 NewNode(javascript()->ToBoolean(ToBooleanHint::kAny), accumulator); | |
| 1296 Node* comperand = jsgraph()->FalseConstant(); | |
| 1297 Node* comparison = | |
| 1298 NewNode(javascript()->StrictEqual(), to_boolean, comperand); | |
| 1299 BuildConditionalJump(comparison); | |
| 1170 } | 1300 } |
| 1171 | 1301 |
| 1172 | 1302 |
| 1173 void BytecodeGraphBuilder::VisitJumpIfToBooleanFalseConstant( | 1303 void BytecodeGraphBuilder::VisitJumpIfToBooleanFalseConstant( |
| 1174 const interpreter::BytecodeArrayIterator& iterator) { | 1304 const interpreter::BytecodeArrayIterator& iterator) { |
| 1175 UNIMPLEMENTED(); | 1305 Node* accumulator = environment()->LookupAccumulator(); |
| 1306 Node* to_boolean = | |
| 1307 NewNode(javascript()->ToBoolean(ToBooleanHint::kAny), accumulator); | |
| 1308 Node* comperand = jsgraph()->FalseConstant(); | |
| 1309 Node* comparison = | |
| 1310 NewNode(javascript()->StrictEqual(), to_boolean, comperand); | |
| 1311 BuildConditionalJump(comparison); | |
| 1176 } | 1312 } |
| 1177 | 1313 |
| 1178 | 1314 |
| 1179 void BytecodeGraphBuilder::VisitJumpIfNull( | 1315 void BytecodeGraphBuilder::VisitJumpIfNull( |
| 1180 const interpreter::BytecodeArrayIterator& iterator) { | 1316 const interpreter::BytecodeArrayIterator& iterator) { |
| 1181 UNIMPLEMENTED(); | 1317 Node* accumulator = environment()->LookupAccumulator(); |
| 1318 Node* comperand = jsgraph()->NullConstant(); | |
| 1319 Node* comparison = | |
| 1320 NewNode(javascript()->StrictEqual(), accumulator, comperand); | |
| 1321 BuildConditionalJump(comparison); | |
| 1182 } | 1322 } |
| 1183 | 1323 |
| 1184 | 1324 |
| 1185 void BytecodeGraphBuilder::VisitJumpIfNullConstant( | 1325 void BytecodeGraphBuilder::VisitJumpIfNullConstant( |
| 1186 const interpreter::BytecodeArrayIterator& iterator) { | 1326 const interpreter::BytecodeArrayIterator& iterator) { |
| 1187 UNIMPLEMENTED(); | 1327 Node* accumulator = environment()->LookupAccumulator(); |
| 1328 Node* comperand = jsgraph()->NullConstant(); | |
| 1329 Node* comparison = | |
| 1330 NewNode(javascript()->StrictEqual(), accumulator, comperand); | |
| 1331 BuildConditionalJump(comparison); | |
| 1188 } | 1332 } |
| 1189 | 1333 |
| 1190 | 1334 |
| 1191 void BytecodeGraphBuilder::VisitJumpIfUndefined( | 1335 void BytecodeGraphBuilder::VisitJumpIfUndefined( |
| 1192 const interpreter::BytecodeArrayIterator& iterator) { | 1336 const interpreter::BytecodeArrayIterator& iterator) { |
| 1193 UNIMPLEMENTED(); | 1337 Node* accumulator = environment()->LookupAccumulator(); |
| 1338 Node* comperand = jsgraph()->UndefinedConstant(); | |
| 1339 Node* comparison = | |
| 1340 NewNode(javascript()->StrictEqual(), accumulator, comperand); | |
| 1341 BuildConditionalJump(comparison); | |
| 1194 } | 1342 } |
| 1195 | 1343 |
| 1196 | 1344 |
| 1197 void BytecodeGraphBuilder::VisitJumpIfUndefinedConstant( | 1345 void BytecodeGraphBuilder::VisitJumpIfUndefinedConstant( |
| 1198 const interpreter::BytecodeArrayIterator& iterator) { | 1346 const interpreter::BytecodeArrayIterator& iterator) { |
| 1199 UNIMPLEMENTED(); | 1347 Node* accumulator = environment()->LookupAccumulator(); |
| 1348 Node* comperand = jsgraph()->UndefinedConstant(); | |
| 1349 Node* comparison = | |
| 1350 NewNode(javascript()->StrictEqual(), accumulator, comperand); | |
| 1351 BuildConditionalJump(comparison); | |
| 1200 } | 1352 } |
| 1201 | 1353 |
| 1202 | 1354 |
| 1203 void BytecodeGraphBuilder::VisitReturn( | 1355 void BytecodeGraphBuilder::VisitReturn( |
| 1204 const interpreter::BytecodeArrayIterator& iterator) { | 1356 const interpreter::BytecodeArrayIterator& iterator) { |
| 1205 Node* control = | 1357 Node* control = |
| 1206 NewNode(common()->Return(), environment()->LookupAccumulator()); | 1358 NewNode(common()->Return(), environment()->LookupAccumulator()); |
| 1207 UpdateControlDependencyToLeaveFunction(control); | 1359 UpdateControlDependencyToLeaveFunction(control); |
| 1360 BuildReturn(); | |
| 1208 } | 1361 } |
| 1209 | 1362 |
| 1210 | 1363 |
| 1211 void BytecodeGraphBuilder::VisitForInPrepare( | 1364 void BytecodeGraphBuilder::VisitForInPrepare( |
| 1212 const interpreter::BytecodeArrayIterator& iterator) { | 1365 const interpreter::BytecodeArrayIterator& iterator) { |
| 1213 UNIMPLEMENTED(); | 1366 UNIMPLEMENTED(); |
| 1214 } | 1367 } |
| 1215 | 1368 |
| 1216 | 1369 |
| 1217 void BytecodeGraphBuilder::VisitForInNext( | 1370 void BytecodeGraphBuilder::VisitForInNext( |
| 1218 const interpreter::BytecodeArrayIterator& iterator) { | 1371 const interpreter::BytecodeArrayIterator& iterator) { |
| 1219 UNIMPLEMENTED(); | 1372 UNIMPLEMENTED(); |
| 1220 } | 1373 } |
| 1221 | 1374 |
| 1222 | 1375 |
| 1223 void BytecodeGraphBuilder::VisitForInDone( | 1376 void BytecodeGraphBuilder::VisitForInDone( |
| 1224 const interpreter::BytecodeArrayIterator& iterator) { | 1377 const interpreter::BytecodeArrayIterator& iterator) { |
| 1225 UNIMPLEMENTED(); | 1378 UNIMPLEMENTED(); |
| 1226 } | 1379 } |
| 1227 | 1380 |
| 1228 | 1381 |
| 1382 void BytecodeGraphBuilder::PrepareForNewBasicBlockVisit() { | |
|
rmcilroy
2015/12/08 13:25:07
nit - I would drop the "new" here, but don't reall
oth
2015/12/09 11:26:45
Done.
| |
| 1383 int block_id = basic_block()->rpo_id(); | |
| 1384 | |
| 1385 DCHECK_NULL(block_environment_infos_[block_id]); | |
| 1386 block_environment_infos_[block_id] = | |
| 1387 new (local_zone()) BlockEnvironmentInfo(); | |
| 1388 | |
| 1389 // Count number of forward and back links to this block | |
| 1390 int back_edges = 0; | |
| 1391 | |
| 1392 // Merge forward links and check for backwards edges | |
| 1393 bool default_done = false; | |
| 1394 for (size_t i = 0; i < basic_block()->incoming_count(); i++) { | |
| 1395 const BytecodeBasicBlock* incoming = basic_block()->incoming(i); | |
| 1396 if (incoming->is_dominated_by(basic_block())) { | |
| 1397 back_edges++; | |
| 1398 } else { | |
| 1399 Environment* preceding_environment; | |
| 1400 if (incoming->if_true() == basic_block()) { | |
| 1401 preceding_environment = | |
| 1402 block_environment_infos_[incoming->rpo_id()]->if_true_environment(); | |
| 1403 } else { | |
| 1404 DCHECK_EQ(incoming->if_false(), basic_block()); | |
| 1405 preceding_environment = block_environment_infos_[incoming->rpo_id()] | |
| 1406 ->if_false_environment(); | |
| 1407 } | |
| 1408 | |
| 1409 DCHECK_NOT_NULL(preceding_environment); | |
| 1410 if (default_done) { | |
|
rmcilroy
2015/12/08 13:25:07
Could you get rid of the default_done boolean by a
oth
2015/12/09 11:26:45
Done.
| |
| 1411 environment()->Merge(preceding_environment); | |
| 1412 } else { | |
| 1413 set_environment(preceding_environment); | |
| 1414 default_done = true; | |
| 1415 } | |
| 1416 } | |
| 1417 } | |
| 1418 | |
| 1419 if (back_edges) { | |
|
rmcilroy
2015/12/08 13:25:07
nit - back_edges != 0
oth
2015/12/09 11:26:45
Done.
| |
| 1420 Environment* loop_env = environment()->CopyForLoop(); | |
| 1421 block_environment_infos_[block_id]->set_loop_header_environment(loop_env); | |
| 1422 } | |
| 1423 } | |
| 1424 | |
| 1425 | |
| 1426 void BytecodeGraphBuilder::CompleteNewBasicBlockVisit() { | |
|
rmcilroy
2015/12/08 13:25:07
ditto
oth
2015/12/09 11:26:45
Done.
| |
| 1427 if (!basic_block()->is_exit()) { | |
| 1428 int last_offset = basic_block()->last_bytecode_offset(); | |
| 1429 interpreter::Bytecode last_bytecode = | |
| 1430 interpreter::Bytecodes::FromByte(bytecode_array()->get(last_offset)); | |
| 1431 if (!interpreter::Bytecodes::IsLocalControlFlow(last_bytecode)) { | |
|
rmcilroy
2015/12/08 13:25:08
Could you do the IsLocalControlFlow check in the b
oth
2015/12/09 11:26:45
Done.
| |
| 1432 DCHECK_NOT_NULL(basic_block()->if_true()); | |
| 1433 DCHECK_NULL(basic_block()->if_false()); | |
| 1434 DCHECK(basic_block()->if_true() != nullptr); | |
| 1435 DCHECK_NOT_NULL(environment()); | |
|
rmcilroy
2015/12/08 13:25:08
Should environment not always be non-null at this
oth
2015/12/09 11:26:45
Change to make the invariant true.
| |
| 1436 int block_id = basic_block()->rpo_id(); | |
| 1437 block_environment_infos_[block_id]->set_if_true_environment( | |
| 1438 environment()); | |
| 1439 BuildBackEdgeIfRequired(basic_block()->if_true()); | |
|
rmcilroy
2015/12/08 13:25:07
Would be good to have a comment here one why what
oth
2015/12/09 11:26:45
Done.
| |
| 1440 } | |
| 1441 } | |
| 1442 set_environment(nullptr); | |
| 1443 } | |
| 1444 | |
| 1445 | |
| 1446 void BytecodeGraphBuilder::BuildReturn() { | |
| 1447 DCHECK_NOT_NULL(basic_block()->if_true()); | |
| 1448 DCHECK_NULL(basic_block()->if_false()); | |
| 1449 int block_id = basic_block()->rpo_id(); | |
| 1450 block_environment_infos_[block_id]->set_if_true_environment(environment()); | |
| 1451 set_environment(nullptr); | |
| 1452 } | |
| 1453 | |
| 1454 | |
| 1455 void BytecodeGraphBuilder::BuildBackEdgeIfRequired(BytecodeBasicBlock* target) { | |
|
rmcilroy
2015/12/08 13:25:07
nit - move above BuildReturn (group BuildReturn /
oth
2015/12/09 11:26:45
Done.
| |
| 1456 if (basic_block()->is_dominated_by(target)) { | |
| 1457 BytecodeBasicBlock* loop_header = target; | |
| 1458 BlockEnvironmentInfo* info = | |
| 1459 block_environment_infos_[loop_header->rpo_id()]; | |
| 1460 info->loop_header_environment()->Merge(environment()); | |
| 1461 } | |
| 1462 } | |
| 1463 | |
| 1464 | |
| 1465 void BytecodeGraphBuilder::BuildJump() { | |
| 1466 DCHECK_NOT_NULL(basic_block()->if_true()); | |
| 1467 DCHECK_NULL(basic_block()->if_false()); | |
| 1468 int block_id = basic_block()->rpo_id(); | |
| 1469 block_environment_infos_[block_id]->set_if_true_environment(environment()); | |
| 1470 BuildBackEdgeIfRequired(basic_block()->if_true()); | |
| 1471 set_environment(nullptr); | |
| 1472 } | |
| 1473 | |
| 1474 | |
| 1475 void BytecodeGraphBuilder::BuildConditionalJump(Node* condition) { | |
| 1476 DCHECK_NOT_NULL(basic_block()->if_true()); | |
| 1477 DCHECK_NOT_NULL(basic_block()->if_false()); | |
| 1478 int block_id = basic_block()->rpo_id(); | |
| 1479 NewBranch(condition); | |
| 1480 // Save environment for false branch. | |
| 1481 Environment* saved_env = environment()->CopyForConditional(); | |
| 1482 // Process true branch. | |
| 1483 NewIfTrue(); | |
| 1484 block_environment_infos_[block_id]->set_if_true_environment(environment()); | |
| 1485 BuildBackEdgeIfRequired(basic_block()->if_true()); | |
| 1486 // Restore environment and process false branch. | |
| 1487 set_environment(saved_env); | |
| 1488 NewIfFalse(); | |
| 1489 block_environment_infos_[block_id]->set_if_false_environment(environment()); | |
| 1490 BuildBackEdgeIfRequired(basic_block()->if_false()); | |
| 1491 set_environment(nullptr); | |
| 1492 } | |
| 1493 | |
| 1494 | |
| 1229 Node** BytecodeGraphBuilder::EnsureInputBufferSize(int size) { | 1495 Node** BytecodeGraphBuilder::EnsureInputBufferSize(int size) { |
| 1230 if (size > input_buffer_size_) { | 1496 if (size > input_buffer_size_) { |
| 1231 size = size + kInputBufferSizeIncrement + input_buffer_size_; | 1497 size = size + kInputBufferSizeIncrement + input_buffer_size_; |
| 1232 input_buffer_ = local_zone()->NewArray<Node*>(size); | 1498 input_buffer_ = local_zone()->NewArray<Node*>(size); |
| 1233 input_buffer_size_ = size; | 1499 input_buffer_size_ = size; |
| 1234 } | 1500 } |
| 1235 return input_buffer_; | 1501 return input_buffer_; |
| 1236 } | 1502 } |
| 1237 | 1503 |
| 1238 | 1504 |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1291 Node* on_success = graph()->NewNode(if_success, result); | 1557 Node* on_success = graph()->NewNode(if_success, result); |
| 1292 environment_->UpdateControlDependency(on_success); | 1558 environment_->UpdateControlDependency(on_success); |
| 1293 } | 1559 } |
| 1294 } | 1560 } |
| 1295 } | 1561 } |
| 1296 | 1562 |
| 1297 return result; | 1563 return result; |
| 1298 } | 1564 } |
| 1299 | 1565 |
| 1300 | 1566 |
| 1567 Node* BytecodeGraphBuilder::NewPhi(int count, Node* input, Node* control) { | |
| 1568 const Operator* phi_op = common()->Phi(kMachAnyTagged, 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 | |
| 1576 // TODO(mstarzinger): Revisit this once we have proper effect states. | |
| 1577 Node* BytecodeGraphBuilder::NewEffectPhi(int count, Node* input, | |
| 1578 Node* control) { | |
| 1579 const Operator* phi_op = common()->EffectPhi(count); | |
| 1580 Node** buffer = EnsureInputBufferSize(count + 1); | |
| 1581 MemsetPointer(buffer, input, count); | |
| 1582 buffer[count] = control; | |
| 1583 return graph()->NewNode(phi_op, count + 1, buffer, true); | |
| 1584 } | |
| 1585 | |
| 1586 | |
| 1301 Node* BytecodeGraphBuilder::MergeControl(Node* control, Node* other) { | 1587 Node* BytecodeGraphBuilder::MergeControl(Node* control, Node* other) { |
| 1302 int inputs = control->op()->ControlInputCount() + 1; | 1588 int inputs = control->op()->ControlInputCount() + 1; |
| 1303 if (control->opcode() == IrOpcode::kLoop) { | 1589 if (control->opcode() == IrOpcode::kLoop) { |
| 1304 // Control node for loop exists, add input. | 1590 // Control node for loop exists, add input. |
| 1305 const Operator* op = common()->Loop(inputs); | 1591 const Operator* op = common()->Loop(inputs); |
| 1306 control->AppendInput(graph_zone(), other); | 1592 control->AppendInput(graph_zone(), other); |
| 1307 NodeProperties::ChangeOp(control, op); | 1593 NodeProperties::ChangeOp(control, op); |
| 1308 } else if (control->opcode() == IrOpcode::kMerge) { | 1594 } else if (control->opcode() == IrOpcode::kMerge) { |
| 1309 // Control node for merge exists, add input. | 1595 // Control node for merge exists, add input. |
| 1310 const Operator* op = common()->Merge(inputs); | 1596 const Operator* op = common()->Merge(inputs); |
| 1311 control->AppendInput(graph_zone(), other); | 1597 control->AppendInput(graph_zone(), other); |
| 1312 NodeProperties::ChangeOp(control, op); | 1598 NodeProperties::ChangeOp(control, op); |
| 1313 } else { | 1599 } else { |
| 1314 // Control node is a singleton, introduce a merge. | 1600 // Control node is a singleton, introduce a merge. |
| 1315 const Operator* op = common()->Merge(inputs); | 1601 const Operator* op = common()->Merge(inputs); |
| 1316 Node* merge_inputs[] = {control, other}; | 1602 Node* merge_inputs[] = {control, other}; |
| 1317 control = graph()->NewNode(op, arraysize(merge_inputs), merge_inputs, true); | 1603 control = graph()->NewNode(op, arraysize(merge_inputs), merge_inputs, true); |
| 1318 } | 1604 } |
| 1319 return control; | 1605 return control; |
| 1320 } | 1606 } |
| 1321 | 1607 |
| 1322 | 1608 |
| 1609 Node* BytecodeGraphBuilder::MergeEffect(Node* value, Node* other, | |
| 1610 Node* control) { | |
| 1611 int inputs = control->op()->ControlInputCount(); | |
| 1612 if (value->opcode() == IrOpcode::kEffectPhi && | |
| 1613 NodeProperties::GetControlInput(value) == control) { | |
| 1614 // Phi already exists, add input. | |
| 1615 value->InsertInput(graph_zone(), inputs - 1, other); | |
| 1616 NodeProperties::ChangeOp(value, common()->EffectPhi(inputs)); | |
| 1617 } else if (value != other) { | |
| 1618 // Phi does not exist yet, introduce one. | |
| 1619 value = NewEffectPhi(inputs, value, control); | |
| 1620 value->ReplaceInput(inputs - 1, other); | |
| 1621 } | |
| 1622 return value; | |
| 1623 } | |
| 1624 | |
| 1625 | |
| 1626 Node* BytecodeGraphBuilder::MergeValue(Node* value, Node* other, | |
| 1627 Node* control) { | |
| 1628 int inputs = control->op()->ControlInputCount(); | |
| 1629 if (value->opcode() == IrOpcode::kPhi && | |
| 1630 NodeProperties::GetControlInput(value) == control) { | |
| 1631 // Phi already exists, add input. | |
| 1632 value->InsertInput(graph_zone(), inputs - 1, other); | |
| 1633 NodeProperties::ChangeOp(value, common()->Phi(kMachAnyTagged, inputs)); | |
| 1634 } else if (value != other) { | |
| 1635 // Phi does not exist yet, introduce one. | |
| 1636 value = NewPhi(inputs, value, control); | |
| 1637 value->ReplaceInput(inputs - 1, other); | |
| 1638 } | |
| 1639 return value; | |
| 1640 } | |
| 1641 | |
| 1642 | |
| 1323 void BytecodeGraphBuilder::UpdateControlDependencyToLeaveFunction(Node* exit) { | 1643 void BytecodeGraphBuilder::UpdateControlDependencyToLeaveFunction(Node* exit) { |
| 1324 if (environment()->IsMarkedAsUnreachable()) return; | 1644 if (environment()->IsMarkedAsUnreachable()) return; |
| 1325 environment()->MarkAsUnreachable(); | 1645 environment()->MarkAsUnreachable(); |
| 1326 exit_controls_.push_back(exit); | 1646 exit_controls_.push_back(exit); |
| 1327 } | 1647 } |
| 1328 | 1648 |
| 1329 } // namespace compiler | 1649 } // namespace compiler |
| 1330 } // namespace internal | 1650 } // namespace internal |
| 1331 } // namespace v8 | 1651 } // namespace v8 |
| OLD | NEW |