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 |