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