| OLD | NEW |
| 1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| 11 // with the distribution. | 11 // with the distribution. |
| (...skipping 303 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 315 arguments()->PrintTo(stream); | 315 arguments()->PrintTo(stream); |
| 316 | 316 |
| 317 stream->Add(" length "); | 317 stream->Add(" length "); |
| 318 length()->PrintTo(stream); | 318 length()->PrintTo(stream); |
| 319 | 319 |
| 320 stream->Add(" index "); | 320 stream->Add(" index "); |
| 321 index()->PrintTo(stream); | 321 index()->PrintTo(stream); |
| 322 } | 322 } |
| 323 | 323 |
| 324 | 324 |
| 325 LChunk::LChunk(HGraph* graph) | |
| 326 : spill_slot_count_(0), | |
| 327 graph_(graph), | |
| 328 instructions_(32), | |
| 329 pointer_maps_(8), | |
| 330 inlined_closures_(1) { | |
| 331 } | |
| 332 | |
| 333 | |
| 334 void LChunk::Verify() const { | 325 void LChunk::Verify() const { |
| 335 // TODO(twuerthinger): Implement verification for chunk. | 326 // TODO(twuerthinger): Implement verification for chunk. |
| 336 } | 327 } |
| 337 | 328 |
| 338 | 329 |
| 339 int LChunk::GetNextSpillIndex(bool is_double) { | 330 int LChunk::GetNextSpillIndex(bool is_double) { |
| 340 // Skip a slot if for a double-width slot. | 331 // Skip a slot if for a double-width slot. |
| 341 if (is_double) spill_slot_count_++; | 332 if (is_double) spill_slot_count_++; |
| 342 return spill_slot_count_++; | 333 return spill_slot_count_++; |
| 343 } | 334 } |
| (...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 465 while (!IsGapAt(index)) index--; | 456 while (!IsGapAt(index)) index--; |
| 466 return index; | 457 return index; |
| 467 } | 458 } |
| 468 | 459 |
| 469 | 460 |
| 470 void LChunk::AddGapMove(int index, LOperand* from, LOperand* to) { | 461 void LChunk::AddGapMove(int index, LOperand* from, LOperand* to) { |
| 471 GetGapAt(index)->GetOrCreateParallelMove(LGap::START)->AddMove(from, to); | 462 GetGapAt(index)->GetOrCreateParallelMove(LGap::START)->AddMove(from, to); |
| 472 } | 463 } |
| 473 | 464 |
| 474 | 465 |
| 475 class LGapNode: public ZoneObject { | |
| 476 public: | |
| 477 explicit LGapNode(LOperand* operand) | |
| 478 : operand_(operand), resolved_(false), visited_id_(-1) { } | |
| 479 | |
| 480 LOperand* operand() const { return operand_; } | |
| 481 bool IsResolved() const { return !IsAssigned() || resolved_; } | |
| 482 void MarkResolved() { | |
| 483 ASSERT(!IsResolved()); | |
| 484 resolved_ = true; | |
| 485 } | |
| 486 int visited_id() const { return visited_id_; } | |
| 487 void set_visited_id(int id) { | |
| 488 ASSERT(id > visited_id_); | |
| 489 visited_id_ = id; | |
| 490 } | |
| 491 | |
| 492 bool IsAssigned() const { return assigned_from_.is_set(); } | |
| 493 LGapNode* assigned_from() const { return assigned_from_.get(); } | |
| 494 void set_assigned_from(LGapNode* n) { assigned_from_.set(n); } | |
| 495 | |
| 496 private: | |
| 497 LOperand* operand_; | |
| 498 SetOncePointer<LGapNode> assigned_from_; | |
| 499 bool resolved_; | |
| 500 int visited_id_; | |
| 501 }; | |
| 502 | |
| 503 | |
| 504 LGapResolver::LGapResolver(const ZoneList<LMoveOperands>* moves, | |
| 505 LOperand* marker_operand) | |
| 506 : nodes_(4), | |
| 507 identified_cycles_(4), | |
| 508 result_(4), | |
| 509 marker_operand_(marker_operand), | |
| 510 next_visited_id_(0) { | |
| 511 for (int i = 0; i < moves->length(); ++i) { | |
| 512 LMoveOperands move = moves->at(i); | |
| 513 if (!move.IsRedundant()) RegisterMove(move); | |
| 514 } | |
| 515 } | |
| 516 | |
| 517 | |
| 518 const ZoneList<LMoveOperands>* LGapResolver::ResolveInReverseOrder() { | |
| 519 for (int i = 0; i < identified_cycles_.length(); ++i) { | |
| 520 ResolveCycle(identified_cycles_[i]); | |
| 521 } | |
| 522 | |
| 523 int unresolved_nodes; | |
| 524 do { | |
| 525 unresolved_nodes = 0; | |
| 526 for (int j = 0; j < nodes_.length(); j++) { | |
| 527 LGapNode* node = nodes_[j]; | |
| 528 if (!node->IsResolved() && node->assigned_from()->IsResolved()) { | |
| 529 AddResultMove(node->assigned_from(), node); | |
| 530 node->MarkResolved(); | |
| 531 } | |
| 532 if (!node->IsResolved()) ++unresolved_nodes; | |
| 533 } | |
| 534 } while (unresolved_nodes > 0); | |
| 535 return &result_; | |
| 536 } | |
| 537 | |
| 538 | |
| 539 void LGapResolver::AddResultMove(LGapNode* from, LGapNode* to) { | |
| 540 AddResultMove(from->operand(), to->operand()); | |
| 541 } | |
| 542 | |
| 543 | |
| 544 void LGapResolver::AddResultMove(LOperand* from, LOperand* to) { | |
| 545 result_.Add(LMoveOperands(from, to)); | |
| 546 } | |
| 547 | |
| 548 | |
| 549 void LGapResolver::ResolveCycle(LGapNode* start) { | |
| 550 ZoneList<LOperand*> circle_operands(8); | |
| 551 circle_operands.Add(marker_operand_); | |
| 552 LGapNode* cur = start; | |
| 553 do { | |
| 554 cur->MarkResolved(); | |
| 555 circle_operands.Add(cur->operand()); | |
| 556 cur = cur->assigned_from(); | |
| 557 } while (cur != start); | |
| 558 circle_operands.Add(marker_operand_); | |
| 559 | |
| 560 for (int i = circle_operands.length() - 1; i > 0; --i) { | |
| 561 LOperand* from = circle_operands[i]; | |
| 562 LOperand* to = circle_operands[i - 1]; | |
| 563 AddResultMove(from, to); | |
| 564 } | |
| 565 } | |
| 566 | |
| 567 | |
| 568 bool LGapResolver::CanReach(LGapNode* a, LGapNode* b, int visited_id) { | |
| 569 ASSERT(a != b); | |
| 570 LGapNode* cur = a; | |
| 571 while (cur != b && cur->visited_id() != visited_id && cur->IsAssigned()) { | |
| 572 cur->set_visited_id(visited_id); | |
| 573 cur = cur->assigned_from(); | |
| 574 } | |
| 575 | |
| 576 return cur == b; | |
| 577 } | |
| 578 | |
| 579 | |
| 580 bool LGapResolver::CanReach(LGapNode* a, LGapNode* b) { | |
| 581 ASSERT(a != b); | |
| 582 return CanReach(a, b, next_visited_id_++); | |
| 583 } | |
| 584 | |
| 585 | |
| 586 void LGapResolver::RegisterMove(LMoveOperands move) { | |
| 587 if (move.from()->IsConstantOperand()) { | |
| 588 // Constant moves should be last in the machine code. Therefore add them | |
| 589 // first to the result set. | |
| 590 AddResultMove(move.from(), move.to()); | |
| 591 } else { | |
| 592 LGapNode* from = LookupNode(move.from()); | |
| 593 LGapNode* to = LookupNode(move.to()); | |
| 594 if (to->IsAssigned() && to->assigned_from() == from) { | |
| 595 move.Eliminate(); | |
| 596 return; | |
| 597 } | |
| 598 ASSERT(!to->IsAssigned()); | |
| 599 if (CanReach(from, to)) { | |
| 600 // This introduces a circle. Save. | |
| 601 identified_cycles_.Add(from); | |
| 602 } | |
| 603 to->set_assigned_from(from); | |
| 604 } | |
| 605 } | |
| 606 | |
| 607 | |
| 608 LGapNode* LGapResolver::LookupNode(LOperand* operand) { | |
| 609 for (int i = 0; i < nodes_.length(); ++i) { | |
| 610 if (nodes_[i]->operand()->Equals(operand)) return nodes_[i]; | |
| 611 } | |
| 612 | |
| 613 // No node found => create a new one. | |
| 614 LGapNode* result = new LGapNode(operand); | |
| 615 nodes_.Add(result); | |
| 616 return result; | |
| 617 } | |
| 618 | |
| 619 | |
| 620 Handle<Object> LChunk::LookupLiteral(LConstantOperand* operand) const { | 466 Handle<Object> LChunk::LookupLiteral(LConstantOperand* operand) const { |
| 621 return HConstant::cast(graph_->LookupValue(operand->index()))->handle(); | 467 return HConstant::cast(graph_->LookupValue(operand->index()))->handle(); |
| 622 } | 468 } |
| 623 | 469 |
| 624 | 470 |
| 625 Representation LChunk::LookupLiteralRepresentation( | 471 Representation LChunk::LookupLiteralRepresentation( |
| 626 LConstantOperand* operand) const { | 472 LConstantOperand* operand) const { |
| 627 return graph_->LookupValue(operand->index())->representation(); | 473 return graph_->LookupValue(operand->index())->representation(); |
| 628 } | 474 } |
| 629 | 475 |
| (...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 826 bool needs_environment = | 672 bool needs_environment = |
| 827 (can_deoptimize == CAN_DEOPTIMIZE_EAGERLY) || !hinstr->HasSideEffects(); | 673 (can_deoptimize == CAN_DEOPTIMIZE_EAGERLY) || !hinstr->HasSideEffects(); |
| 828 if (needs_environment && !instr->HasEnvironment()) { | 674 if (needs_environment && !instr->HasEnvironment()) { |
| 829 instr = AssignEnvironment(instr); | 675 instr = AssignEnvironment(instr); |
| 830 } | 676 } |
| 831 | 677 |
| 832 return instr; | 678 return instr; |
| 833 } | 679 } |
| 834 | 680 |
| 835 | 681 |
| 682 LInstruction* LChunkBuilder::MarkAsSaveDoubles(LInstruction* instr) { |
| 683 allocator_->MarkAsSaveDoubles(); |
| 684 return instr; |
| 685 } |
| 686 |
| 687 |
| 836 LInstruction* LChunkBuilder::AssignPointerMap(LInstruction* instr) { | 688 LInstruction* LChunkBuilder::AssignPointerMap(LInstruction* instr) { |
| 837 ASSERT(!instr->HasPointerMap()); | 689 ASSERT(!instr->HasPointerMap()); |
| 838 instr->set_pointer_map(new LPointerMap(position_)); | 690 instr->set_pointer_map(new LPointerMap(position_)); |
| 839 return instr; | 691 return instr; |
| 840 } | 692 } |
| 841 | 693 |
| 842 | 694 |
| 843 LInstruction* LChunkBuilder::Define(LInstruction* instr, LUnallocated* result) { | 695 LInstruction* LChunkBuilder::Define(LInstruction* instr, LUnallocated* result) { |
| 844 allocator_->RecordDefinition(current_instruction_, result); | 696 allocator_->RecordDefinition(current_instruction_, result); |
| 845 instr->set_result(result); | 697 instr->set_result(result); |
| (...skipping 404 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1250 second_id); | 1102 second_id); |
| 1251 } else if (v->IsCompareJSObjectEq()) { | 1103 } else if (v->IsCompareJSObjectEq()) { |
| 1252 HCompareJSObjectEq* compare = HCompareJSObjectEq::cast(v); | 1104 HCompareJSObjectEq* compare = HCompareJSObjectEq::cast(v); |
| 1253 return new LCmpJSObjectEqAndBranch(UseRegisterAtStart(compare->left()), | 1105 return new LCmpJSObjectEqAndBranch(UseRegisterAtStart(compare->left()), |
| 1254 UseRegisterAtStart(compare->right()), | 1106 UseRegisterAtStart(compare->right()), |
| 1255 first_id, | 1107 first_id, |
| 1256 second_id); | 1108 second_id); |
| 1257 } else if (v->IsInstanceOf()) { | 1109 } else if (v->IsInstanceOf()) { |
| 1258 HInstanceOf* instance_of = HInstanceOf::cast(v); | 1110 HInstanceOf* instance_of = HInstanceOf::cast(v); |
| 1259 LInstruction* result = | 1111 LInstruction* result = |
| 1260 new LInstanceOfAndBranch(UseFixed(instance_of->left(), eax), | 1112 new LInstanceOfAndBranch( |
| 1261 UseFixed(instance_of->right(), edx), | 1113 UseFixed(instance_of->left(), InstanceofStub::left()), |
| 1262 first_id, | 1114 UseFixed(instance_of->right(), InstanceofStub::right()), |
| 1263 second_id); | 1115 first_id, |
| 1116 second_id); |
| 1264 return MarkAsCall(result, instr); | 1117 return MarkAsCall(result, instr); |
| 1265 } else if (v->IsTypeofIs()) { | 1118 } else if (v->IsTypeofIs()) { |
| 1266 HTypeofIs* typeof_is = HTypeofIs::cast(v); | 1119 HTypeofIs* typeof_is = HTypeofIs::cast(v); |
| 1267 return new LTypeofIsAndBranch(UseTempRegister(typeof_is->value()), | 1120 return new LTypeofIsAndBranch(UseTempRegister(typeof_is->value()), |
| 1268 first_id, | 1121 first_id, |
| 1269 second_id); | 1122 second_id); |
| 1270 } else { | 1123 } else { |
| 1271 if (v->IsConstant()) { | 1124 if (v->IsConstant()) { |
| 1272 if (HConstant::cast(v)->handle()->IsTrue()) { | 1125 if (HConstant::cast(v)->handle()->IsTrue()) { |
| 1273 return new LGoto(first_id); | 1126 return new LGoto(first_id); |
| 1274 } else if (HConstant::cast(v)->handle()->IsFalse()) { | 1127 } else if (HConstant::cast(v)->handle()->IsFalse()) { |
| 1275 return new LGoto(second_id); | 1128 return new LGoto(second_id); |
| 1276 } | 1129 } |
| 1277 } | 1130 } |
| 1278 Abort("Undefined compare before branch"); | 1131 Abort("Undefined compare before branch"); |
| 1279 return NULL; | 1132 return NULL; |
| 1280 } | 1133 } |
| 1281 } | 1134 } |
| 1282 return new LBranch(UseRegisterAtStart(v), first_id, second_id); | 1135 return new LBranch(UseRegisterAtStart(v), first_id, second_id); |
| 1283 } | 1136 } |
| 1284 | 1137 |
| 1285 | 1138 |
| 1286 LInstruction* LChunkBuilder::DoCompareMapAndBranch( | 1139 LInstruction* LChunkBuilder::DoCompareMapAndBranch( |
| 1287 HCompareMapAndBranch* instr) { | 1140 HCompareMapAndBranch* instr) { |
| 1288 ASSERT(instr->value()->representation().IsTagged()); | 1141 ASSERT(instr->value()->representation().IsTagged()); |
| 1289 LOperand* value = UseRegisterAtStart(instr->value()); | 1142 LOperand* value = UseRegisterAtStart(instr->value()); |
| 1290 HBasicBlock* first = instr->FirstSuccessor(); | 1143 return new LCmpMapAndBranch(value); |
| 1291 HBasicBlock* second = instr->SecondSuccessor(); | |
| 1292 return new LCmpMapAndBranch(value, | |
| 1293 instr->map(), | |
| 1294 first->block_id(), | |
| 1295 second->block_id()); | |
| 1296 } | 1144 } |
| 1297 | 1145 |
| 1298 | 1146 |
| 1299 LInstruction* LChunkBuilder::DoArgumentsLength(HArgumentsLength* length) { | 1147 LInstruction* LChunkBuilder::DoArgumentsLength(HArgumentsLength* length) { |
| 1300 return DefineAsRegister(new LArgumentsLength(Use(length->value()))); | 1148 return DefineAsRegister(new LArgumentsLength(Use(length->value()))); |
| 1301 } | 1149 } |
| 1302 | 1150 |
| 1303 | 1151 |
| 1304 LInstruction* LChunkBuilder::DoArgumentsElements(HArgumentsElements* elems) { | 1152 LInstruction* LChunkBuilder::DoArgumentsElements(HArgumentsElements* elems) { |
| 1305 return DefineAsRegister(new LArgumentsElements); | 1153 return DefineAsRegister(new LArgumentsElements); |
| 1306 } | 1154 } |
| 1307 | 1155 |
| 1308 | 1156 |
| 1309 LInstruction* LChunkBuilder::DoInstanceOf(HInstanceOf* instr) { | 1157 LInstruction* LChunkBuilder::DoInstanceOf(HInstanceOf* instr) { |
| 1310 LInstruction* result = | 1158 LInstruction* result = |
| 1311 new LInstanceOf(UseFixed(instr->left(), eax), | 1159 new LInstanceOf(UseFixed(instr->left(), InstanceofStub::left()), |
| 1312 UseFixed(instr->right(), edx)); | 1160 UseFixed(instr->right(), InstanceofStub::right())); |
| 1313 return MarkAsCall(DefineFixed(result, eax), instr); | 1161 return MarkAsCall(DefineFixed(result, eax), instr); |
| 1314 } | 1162 } |
| 1315 | 1163 |
| 1316 | 1164 |
| 1165 LInstruction* LChunkBuilder::DoInstanceOfKnownGlobal( |
| 1166 HInstanceOfKnownGlobal* instr) { |
| 1167 LInstruction* result = |
| 1168 new LInstanceOfKnownGlobal( |
| 1169 UseFixed(instr->value(), InstanceofStub::left()), |
| 1170 FixedTemp(edi)); |
| 1171 MarkAsSaveDoubles(result); |
| 1172 return AssignEnvironment(AssignPointerMap(DefineFixed(result, eax))); |
| 1173 } |
| 1174 |
| 1175 |
| 1317 LInstruction* LChunkBuilder::DoApplyArguments(HApplyArguments* instr) { | 1176 LInstruction* LChunkBuilder::DoApplyArguments(HApplyArguments* instr) { |
| 1318 LOperand* function = UseFixed(instr->function(), edi); | 1177 LOperand* function = UseFixed(instr->function(), edi); |
| 1319 LOperand* receiver = UseFixed(instr->receiver(), eax); | 1178 LOperand* receiver = UseFixed(instr->receiver(), eax); |
| 1320 LOperand* length = UseRegisterAtStart(instr->length()); | 1179 LOperand* length = UseRegisterAtStart(instr->length()); |
| 1321 LOperand* elements = UseRegisterAtStart(instr->elements()); | 1180 LOperand* elements = UseRegisterAtStart(instr->elements()); |
| 1322 LInstruction* result = new LApplyArguments(function, | 1181 LInstruction* result = new LApplyArguments(function, |
| 1323 receiver, | 1182 receiver, |
| 1324 length, | 1183 length, |
| 1325 elements); | 1184 elements); |
| 1326 return MarkAsCall(DefineFixed(result, eax), instr, CAN_DEOPTIMIZE_EAGERLY); | 1185 return MarkAsCall(DefineFixed(result, eax), instr, CAN_DEOPTIMIZE_EAGERLY); |
| (...skipping 781 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2108 void LPointerMap::PrintTo(StringStream* stream) const { | 1967 void LPointerMap::PrintTo(StringStream* stream) const { |
| 2109 stream->Add("{"); | 1968 stream->Add("{"); |
| 2110 for (int i = 0; i < pointer_operands_.length(); ++i) { | 1969 for (int i = 0; i < pointer_operands_.length(); ++i) { |
| 2111 if (i != 0) stream->Add(";"); | 1970 if (i != 0) stream->Add(";"); |
| 2112 pointer_operands_[i]->PrintTo(stream); | 1971 pointer_operands_[i]->PrintTo(stream); |
| 2113 } | 1972 } |
| 2114 stream->Add("} @%d", position()); | 1973 stream->Add("} @%d", position()); |
| 2115 } | 1974 } |
| 2116 | 1975 |
| 2117 } } // namespace v8::internal | 1976 } } // namespace v8::internal |
| OLD | NEW |