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++) { | |
Michael Starzinger
2015/12/16 12:40:12
nit: s/int/size_t/ here and drop the static_cast i
oth
2015/12/16 14:17:06
Done.
| |
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); | |
Michael Starzinger
2015/12/16 12:40:12
nit: Can we reorder this function so that it follo
oth
2015/12/16 14:17:06
Done.
| |
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 int current_offset = iterator.current_offset(); |
335 if (analysis.is_reachable(current_offset)) { | |
336 MergeEnvironmentsOfForwardBranches(current_offset); | |
337 BuildLoopHeaderForBackwardBranches(current_offset); | |
338 | |
339 switch (iterator.current_bytecode()) { | |
253 #define BYTECODE_CASE(name, ...) \ | 340 #define BYTECODE_CASE(name, ...) \ |
254 case interpreter::Bytecode::k##name: \ | 341 case interpreter::Bytecode::k##name: \ |
255 Visit##name(iterator); \ | 342 Visit##name(iterator); \ |
256 break; | 343 break; |
257 BYTECODE_LIST(BYTECODE_CASE) | 344 BYTECODE_LIST(BYTECODE_CASE) |
258 #undef BYTECODE_CODE | 345 #undef BYTECODE_CODE |
346 } | |
259 } | 347 } |
260 iterator.Advance(); | 348 iterator.Advance(); |
261 } | 349 } |
350 set_branch_analysis(nullptr); | |
351 set_bytecode_iterator(nullptr); | |
262 } | 352 } |
263 | 353 |
264 | 354 |
265 void BytecodeGraphBuilder::VisitLdaZero( | 355 void BytecodeGraphBuilder::VisitLdaZero( |
266 const interpreter::BytecodeArrayIterator& iterator) { | 356 const interpreter::BytecodeArrayIterator& iterator) { |
267 Node* node = jsgraph()->ZeroConstant(); | 357 Node* node = jsgraph()->ZeroConstant(); |
268 environment()->BindAccumulator(node); | 358 environment()->BindAccumulator(node); |
269 } | 359 } |
270 | 360 |
271 | 361 |
(...skipping 895 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1167 | 1257 |
1168 | 1258 |
1169 void BytecodeGraphBuilder::VisitToObject( | 1259 void BytecodeGraphBuilder::VisitToObject( |
1170 const interpreter::BytecodeArrayIterator& iterator) { | 1260 const interpreter::BytecodeArrayIterator& iterator) { |
1171 BuildCastOperator(javascript()->ToObject(), iterator); | 1261 BuildCastOperator(javascript()->ToObject(), iterator); |
1172 } | 1262 } |
1173 | 1263 |
1174 | 1264 |
1175 void BytecodeGraphBuilder::VisitJump( | 1265 void BytecodeGraphBuilder::VisitJump( |
1176 const interpreter::BytecodeArrayIterator& iterator) { | 1266 const interpreter::BytecodeArrayIterator& iterator) { |
1177 UNIMPLEMENTED(); | 1267 BuildJump(); |
1178 } | 1268 } |
1179 | 1269 |
1180 | 1270 |
1181 void BytecodeGraphBuilder::VisitJumpConstant( | 1271 void BytecodeGraphBuilder::VisitJumpConstant( |
1182 const interpreter::BytecodeArrayIterator& iterator) { | 1272 const interpreter::BytecodeArrayIterator& iterator) { |
1183 UNIMPLEMENTED(); | 1273 BuildJump(); |
1184 } | 1274 } |
1185 | 1275 |
1186 | 1276 |
1187 void BytecodeGraphBuilder::VisitJumpIfTrue( | 1277 void BytecodeGraphBuilder::VisitJumpIfTrue( |
1188 const interpreter::BytecodeArrayIterator& iterator) { | 1278 const interpreter::BytecodeArrayIterator& iterator) { |
1189 UNIMPLEMENTED(); | 1279 Node* condition = BuildCondition(jsgraph()->TrueConstant()); |
1280 BuildConditionalJump(condition); | |
1190 } | 1281 } |
1191 | 1282 |
1192 | 1283 |
1193 void BytecodeGraphBuilder::VisitJumpIfTrueConstant( | 1284 void BytecodeGraphBuilder::VisitJumpIfTrueConstant( |
1194 const interpreter::BytecodeArrayIterator& iterator) { | 1285 const interpreter::BytecodeArrayIterator& iterator) { |
1195 UNIMPLEMENTED(); | 1286 Node* condition = BuildCondition(jsgraph()->TrueConstant()); |
1287 BuildConditionalJump(condition); | |
1196 } | 1288 } |
1197 | 1289 |
1198 | 1290 |
1199 void BytecodeGraphBuilder::VisitJumpIfFalse( | 1291 void BytecodeGraphBuilder::VisitJumpIfFalse( |
1200 const interpreter::BytecodeArrayIterator& iterator) { | 1292 const interpreter::BytecodeArrayIterator& iterator) { |
1201 UNIMPLEMENTED(); | 1293 Node* condition = BuildCondition(jsgraph()->FalseConstant()); |
1294 BuildConditionalJump(condition); | |
1202 } | 1295 } |
1203 | 1296 |
1204 | 1297 |
1205 void BytecodeGraphBuilder::VisitJumpIfFalseConstant( | 1298 void BytecodeGraphBuilder::VisitJumpIfFalseConstant( |
1206 const interpreter::BytecodeArrayIterator& iterator) { | 1299 const interpreter::BytecodeArrayIterator& iterator) { |
1207 UNIMPLEMENTED(); | 1300 Node* condition = BuildCondition(jsgraph()->FalseConstant()); |
1301 BuildConditionalJump(condition); | |
1208 } | 1302 } |
1209 | 1303 |
1210 | 1304 |
1211 void BytecodeGraphBuilder::VisitJumpIfToBooleanTrue( | 1305 void BytecodeGraphBuilder::VisitJumpIfToBooleanTrue( |
1212 const interpreter::BytecodeArrayIterator& iterator) { | 1306 const interpreter::BytecodeArrayIterator& iterator) { |
1213 UNIMPLEMENTED(); | 1307 Node* condition = BuildToBooleanCondition(jsgraph()->TrueConstant()); |
1308 BuildConditionalJump(condition); | |
1214 } | 1309 } |
1215 | 1310 |
1216 | 1311 |
1217 void BytecodeGraphBuilder::VisitJumpIfToBooleanTrueConstant( | 1312 void BytecodeGraphBuilder::VisitJumpIfToBooleanTrueConstant( |
1218 const interpreter::BytecodeArrayIterator& iterator) { | 1313 const interpreter::BytecodeArrayIterator& iterator) { |
1219 UNIMPLEMENTED(); | 1314 Node* condition = BuildToBooleanCondition(jsgraph()->TrueConstant()); |
1315 BuildConditionalJump(condition); | |
1220 } | 1316 } |
1221 | 1317 |
1222 | 1318 |
1223 void BytecodeGraphBuilder::VisitJumpIfToBooleanFalse( | 1319 void BytecodeGraphBuilder::VisitJumpIfToBooleanFalse( |
1224 const interpreter::BytecodeArrayIterator& iterator) { | 1320 const interpreter::BytecodeArrayIterator& iterator) { |
1225 UNIMPLEMENTED(); | 1321 Node* condition = BuildToBooleanCondition(jsgraph()->FalseConstant()); |
1322 BuildConditionalJump(condition); | |
1226 } | 1323 } |
1227 | 1324 |
1228 | 1325 |
1229 void BytecodeGraphBuilder::VisitJumpIfToBooleanFalseConstant( | 1326 void BytecodeGraphBuilder::VisitJumpIfToBooleanFalseConstant( |
1230 const interpreter::BytecodeArrayIterator& iterator) { | 1327 const interpreter::BytecodeArrayIterator& iterator) { |
1231 UNIMPLEMENTED(); | 1328 Node* condition = BuildToBooleanCondition(jsgraph()->FalseConstant()); |
1329 BuildConditionalJump(condition); | |
1232 } | 1330 } |
1233 | 1331 |
1234 | 1332 |
1235 void BytecodeGraphBuilder::VisitJumpIfNull( | 1333 void BytecodeGraphBuilder::VisitJumpIfNull( |
1236 const interpreter::BytecodeArrayIterator& iterator) { | 1334 const interpreter::BytecodeArrayIterator& iterator) { |
1237 UNIMPLEMENTED(); | 1335 Node* condition = BuildCondition(jsgraph()->NullConstant()); |
1336 BuildConditionalJump(condition); | |
1238 } | 1337 } |
1239 | 1338 |
1240 | 1339 |
1241 void BytecodeGraphBuilder::VisitJumpIfNullConstant( | 1340 void BytecodeGraphBuilder::VisitJumpIfNullConstant( |
1242 const interpreter::BytecodeArrayIterator& iterator) { | 1341 const interpreter::BytecodeArrayIterator& iterator) { |
1243 UNIMPLEMENTED(); | 1342 Node* condition = BuildCondition(jsgraph()->NullConstant()); |
1343 BuildConditionalJump(condition); | |
1244 } | 1344 } |
1245 | 1345 |
1246 | 1346 |
1247 void BytecodeGraphBuilder::VisitJumpIfUndefined( | 1347 void BytecodeGraphBuilder::VisitJumpIfUndefined( |
1248 const interpreter::BytecodeArrayIterator& iterator) { | 1348 const interpreter::BytecodeArrayIterator& iterator) { |
1249 UNIMPLEMENTED(); | 1349 Node* condition = BuildCondition(jsgraph()->UndefinedConstant()); |
1350 BuildConditionalJump(condition); | |
1250 } | 1351 } |
1251 | 1352 |
1252 | 1353 |
1253 void BytecodeGraphBuilder::VisitJumpIfUndefinedConstant( | 1354 void BytecodeGraphBuilder::VisitJumpIfUndefinedConstant( |
1254 const interpreter::BytecodeArrayIterator& iterator) { | 1355 const interpreter::BytecodeArrayIterator& iterator) { |
1255 UNIMPLEMENTED(); | 1356 Node* condition = BuildCondition(jsgraph()->UndefinedConstant()); |
1357 BuildConditionalJump(condition); | |
1256 } | 1358 } |
1257 | 1359 |
1258 | 1360 |
1259 void BytecodeGraphBuilder::VisitReturn( | 1361 void BytecodeGraphBuilder::VisitReturn( |
1260 const interpreter::BytecodeArrayIterator& iterator) { | 1362 const interpreter::BytecodeArrayIterator& iterator) { |
1261 Node* control = | 1363 Node* control = |
1262 NewNode(common()->Return(), environment()->LookupAccumulator()); | 1364 NewNode(common()->Return(), environment()->LookupAccumulator()); |
1263 UpdateControlDependencyToLeaveFunction(control); | 1365 UpdateControlDependencyToLeaveFunction(control); |
1366 set_environment(nullptr); | |
1264 } | 1367 } |
1265 | 1368 |
1266 | 1369 |
1267 void BytecodeGraphBuilder::VisitForInPrepare( | 1370 void BytecodeGraphBuilder::VisitForInPrepare( |
1268 const interpreter::BytecodeArrayIterator& iterator) { | 1371 const interpreter::BytecodeArrayIterator& iterator) { |
1269 UNIMPLEMENTED(); | 1372 UNIMPLEMENTED(); |
1270 } | 1373 } |
1271 | 1374 |
1272 | 1375 |
1273 void BytecodeGraphBuilder::VisitForInNext( | 1376 void BytecodeGraphBuilder::VisitForInNext( |
1274 const interpreter::BytecodeArrayIterator& iterator) { | 1377 const interpreter::BytecodeArrayIterator& iterator) { |
1275 UNIMPLEMENTED(); | 1378 UNIMPLEMENTED(); |
1276 } | 1379 } |
1277 | 1380 |
1278 | 1381 |
1279 void BytecodeGraphBuilder::VisitForInDone( | 1382 void BytecodeGraphBuilder::VisitForInDone( |
1280 const interpreter::BytecodeArrayIterator& iterator) { | 1383 const interpreter::BytecodeArrayIterator& iterator) { |
1281 UNIMPLEMENTED(); | 1384 UNIMPLEMENTED(); |
1282 } | 1385 } |
1283 | 1386 |
1284 | 1387 |
1388 void BytecodeGraphBuilder::MergeEnvironmentsOfBackwardBranches( | |
1389 int source_offset, int target_offset) { | |
1390 DCHECK_GE(source_offset, target_offset); | |
1391 const ZoneVector<int>* back_branches = | |
1392 branch_analysis()->BackwardBranchesTargetting(target_offset); | |
1393 if (back_branches->back() == source_offset) { | |
1394 // The set of back branches is complete, merge them. | |
1395 Environment* environment = merge_environments_[back_branches->at(0)]; | |
Michael Starzinger
2015/12/16 12:40:12
nit: s/environment/merged/ for readability.
oth
2015/12/16 14:17:06
Done.
| |
1396 for (size_t i = 1; i < back_branches->size(); i++) { | |
Michael Starzinger
2015/12/16 12:40:12
nit: Would it be possible to have a similar check
oth
2015/12/16 14:17:06
Done.
| |
1397 environment->Merge(merge_environments_[back_branches->at(i)]); | |
1398 } | |
1399 // And now merge with loop header environment created when loop | |
1400 // header was visited. | |
1401 loop_header_environments_[target_offset]->Merge(environment); | |
1402 } | |
1403 } | |
1404 | |
1405 | |
1406 void BytecodeGraphBuilder::MergeEnvironmentsOfForwardBranches( | |
1407 int source_offset) { | |
1408 if (branch_analysis()->forward_branches_target(source_offset)) { | |
1409 // Merge environments of branches that reach this bytecode. | |
1410 auto branch_sites = | |
1411 branch_analysis()->ForwardBranchesTargetting(source_offset); | |
1412 Environment* merged = merge_environments_[branch_sites->at(0)]; | |
1413 for (size_t i = 1; i < branch_sites->size(); i++) { | |
1414 DCHECK_LT(branch_sites->at(i), source_offset); | |
1415 merged->Merge(merge_environments_[branch_sites->at(i)]); | |
1416 } | |
1417 if (environment()) { | |
1418 merged->Merge(environment()); | |
1419 } | |
1420 set_environment(merged); | |
1421 } | |
1422 } | |
1423 | |
1424 | |
1425 void BytecodeGraphBuilder::BuildLoopHeaderForBackwardBranches( | |
1426 int source_offset) { | |
1427 if (branch_analysis()->backward_branches_target(source_offset)) { | |
1428 // Add loop header and store a copy so we can connect merged back | |
1429 // edge inputs to the loop header. | |
1430 loop_header_environments_[source_offset] = environment()->CopyForLoop(); | |
1431 } | |
1432 } | |
1433 | |
1434 | |
1435 void BytecodeGraphBuilder::BuildJump(int source_offset, int target_offset) { | |
1436 DCHECK_NULL(merge_environments_[source_offset]); | |
1437 merge_environments_[source_offset] = environment(); | |
1438 if (source_offset >= target_offset) { | |
1439 MergeEnvironmentsOfBackwardBranches(source_offset, target_offset); | |
1440 } | |
1441 set_environment(nullptr); | |
1442 } | |
1443 | |
1444 | |
1445 void BytecodeGraphBuilder::BuildJump() { | |
1446 int source_offset = bytecode_iterator()->current_offset(); | |
1447 int target_offset = bytecode_iterator()->GetJumpTargetOffset(); | |
1448 BuildJump(source_offset, target_offset); | |
1449 } | |
1450 | |
1451 | |
1452 void BytecodeGraphBuilder::BuildConditionalJump(Node* condition) { | |
1453 int source_offset = bytecode_iterator()->current_offset(); | |
1454 NewBranch(condition); | |
1455 Environment* if_false_environment = environment()->CopyForConditional(); | |
1456 NewIfTrue(); | |
1457 BuildJump(source_offset, bytecode_iterator()->GetJumpTargetOffset()); | |
1458 set_environment(if_false_environment); | |
1459 NewIfFalse(); | |
1460 } | |
1461 | |
1462 | |
1463 Node* BytecodeGraphBuilder::BuildCondition(Node* comperand) { | |
1464 Node* accumulator = environment()->LookupAccumulator(); | |
1465 return NewNode(javascript()->StrictEqual(), accumulator, comperand); | |
1466 } | |
1467 | |
1468 | |
1469 Node* BytecodeGraphBuilder::BuildToBooleanCondition(Node* comperand) { | |
1470 Node* accumulator = environment()->LookupAccumulator(); | |
1471 Node* to_boolean = | |
1472 NewNode(javascript()->ToBoolean(ToBooleanHint::kAny), accumulator); | |
1473 return NewNode(javascript()->StrictEqual(), to_boolean, comperand); | |
1474 } | |
1475 | |
1476 | |
1285 Node** BytecodeGraphBuilder::EnsureInputBufferSize(int size) { | 1477 Node** BytecodeGraphBuilder::EnsureInputBufferSize(int size) { |
1286 if (size > input_buffer_size_) { | 1478 if (size > input_buffer_size_) { |
1287 size = size + kInputBufferSizeIncrement + input_buffer_size_; | 1479 size = size + kInputBufferSizeIncrement + input_buffer_size_; |
1288 input_buffer_ = local_zone()->NewArray<Node*>(size); | 1480 input_buffer_ = local_zone()->NewArray<Node*>(size); |
1289 input_buffer_size_ = size; | 1481 input_buffer_size_ = size; |
1290 } | 1482 } |
1291 return input_buffer_; | 1483 return input_buffer_; |
1292 } | 1484 } |
1293 | 1485 |
1294 | 1486 |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1347 Node* on_success = graph()->NewNode(if_success, result); | 1539 Node* on_success = graph()->NewNode(if_success, result); |
1348 environment_->UpdateControlDependency(on_success); | 1540 environment_->UpdateControlDependency(on_success); |
1349 } | 1541 } |
1350 } | 1542 } |
1351 } | 1543 } |
1352 | 1544 |
1353 return result; | 1545 return result; |
1354 } | 1546 } |
1355 | 1547 |
1356 | 1548 |
1549 Node* BytecodeGraphBuilder::NewPhi(int count, Node* input, Node* control) { | |
1550 const Operator* phi_op = common()->Phi(MachineRepresentation::kTagged, count); | |
1551 Node** buffer = EnsureInputBufferSize(count + 1); | |
1552 MemsetPointer(buffer, input, count); | |
1553 buffer[count] = control; | |
1554 return graph()->NewNode(phi_op, count + 1, buffer, true); | |
1555 } | |
1556 | |
1557 | |
1558 // TODO(mstarzinger): Revisit this once we have proper effect states. | |
Michael Starzinger
2015/12/16 12:40:12
nit: This TODO is outdated, I should remove it fro
oth
2015/12/16 14:17:06
Done.
| |
1559 Node* BytecodeGraphBuilder::NewEffectPhi(int count, Node* input, | |
1560 Node* control) { | |
1561 const Operator* phi_op = common()->EffectPhi(count); | |
1562 Node** buffer = EnsureInputBufferSize(count + 1); | |
1563 MemsetPointer(buffer, input, count); | |
1564 buffer[count] = control; | |
1565 return graph()->NewNode(phi_op, count + 1, buffer, true); | |
1566 } | |
1567 | |
1568 | |
1357 Node* BytecodeGraphBuilder::MergeControl(Node* control, Node* other) { | 1569 Node* BytecodeGraphBuilder::MergeControl(Node* control, Node* other) { |
1358 int inputs = control->op()->ControlInputCount() + 1; | 1570 int inputs = control->op()->ControlInputCount() + 1; |
1359 if (control->opcode() == IrOpcode::kLoop) { | 1571 if (control->opcode() == IrOpcode::kLoop) { |
1360 // Control node for loop exists, add input. | 1572 // Control node for loop exists, add input. |
1361 const Operator* op = common()->Loop(inputs); | 1573 const Operator* op = common()->Loop(inputs); |
1362 control->AppendInput(graph_zone(), other); | 1574 control->AppendInput(graph_zone(), other); |
1363 NodeProperties::ChangeOp(control, op); | 1575 NodeProperties::ChangeOp(control, op); |
1364 } else if (control->opcode() == IrOpcode::kMerge) { | 1576 } else if (control->opcode() == IrOpcode::kMerge) { |
1365 // Control node for merge exists, add input. | 1577 // Control node for merge exists, add input. |
1366 const Operator* op = common()->Merge(inputs); | 1578 const Operator* op = common()->Merge(inputs); |
1367 control->AppendInput(graph_zone(), other); | 1579 control->AppendInput(graph_zone(), other); |
1368 NodeProperties::ChangeOp(control, op); | 1580 NodeProperties::ChangeOp(control, op); |
1369 } else { | 1581 } else { |
1370 // Control node is a singleton, introduce a merge. | 1582 // Control node is a singleton, introduce a merge. |
1371 const Operator* op = common()->Merge(inputs); | 1583 const Operator* op = common()->Merge(inputs); |
1372 Node* merge_inputs[] = {control, other}; | 1584 Node* merge_inputs[] = {control, other}; |
1373 control = graph()->NewNode(op, arraysize(merge_inputs), merge_inputs, true); | 1585 control = graph()->NewNode(op, arraysize(merge_inputs), merge_inputs, true); |
1374 } | 1586 } |
1375 return control; | 1587 return control; |
1376 } | 1588 } |
1377 | 1589 |
1378 | 1590 |
1591 Node* BytecodeGraphBuilder::MergeEffect(Node* value, Node* other, | |
1592 Node* control) { | |
1593 int inputs = control->op()->ControlInputCount(); | |
1594 if (value->opcode() == IrOpcode::kEffectPhi && | |
1595 NodeProperties::GetControlInput(value) == control) { | |
1596 // Phi already exists, add input. | |
1597 value->InsertInput(graph_zone(), inputs - 1, other); | |
1598 NodeProperties::ChangeOp(value, common()->EffectPhi(inputs)); | |
1599 } else if (value != other) { | |
1600 // Phi does not exist yet, introduce one. | |
1601 value = NewEffectPhi(inputs, value, control); | |
1602 value->ReplaceInput(inputs - 1, other); | |
1603 } | |
1604 return value; | |
1605 } | |
1606 | |
1607 | |
1608 Node* BytecodeGraphBuilder::MergeValue(Node* value, Node* other, | |
1609 Node* control) { | |
1610 int inputs = control->op()->ControlInputCount(); | |
1611 if (value->opcode() == IrOpcode::kPhi && | |
1612 NodeProperties::GetControlInput(value) == control) { | |
1613 // Phi already exists, add input. | |
1614 value->InsertInput(graph_zone(), inputs - 1, other); | |
1615 NodeProperties::ChangeOp( | |
1616 value, common()->Phi(MachineRepresentation::kTagged, inputs)); | |
1617 } else if (value != other) { | |
1618 // Phi does not exist yet, introduce one. | |
1619 value = NewPhi(inputs, value, control); | |
1620 | |
Michael Starzinger
2015/12/16 12:40:12
nit: Stray empty newline.
oth
2015/12/16 14:17:06
Done.
| |
1621 value->ReplaceInput(inputs - 1, other); | |
1622 } | |
1623 return value; | |
1624 } | |
1625 | |
1626 | |
1379 void BytecodeGraphBuilder::UpdateControlDependencyToLeaveFunction(Node* exit) { | 1627 void BytecodeGraphBuilder::UpdateControlDependencyToLeaveFunction(Node* exit) { |
1380 if (environment()->IsMarkedAsUnreachable()) return; | 1628 if (environment()->IsMarkedAsUnreachable()) return; |
1381 environment()->MarkAsUnreachable(); | 1629 environment()->MarkAsUnreachable(); |
1382 exit_controls_.push_back(exit); | 1630 exit_controls_.push_back(exit); |
1383 } | 1631 } |
1384 | 1632 |
1385 } // namespace compiler | 1633 } // namespace compiler |
1386 } // namespace internal | 1634 } // namespace internal |
1387 } // namespace v8 | 1635 } // namespace v8 |
OLD | NEW |