| OLD | NEW |
| 1 // Copyright 2011 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 |
| (...skipping 11 matching lines...) Expand all Loading... |
| 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 27 | 27 |
| 28 #include "v8.h" | 28 #include "v8.h" |
| 29 | 29 |
| 30 #if defined(V8_TARGET_ARCH_IA32) | 30 #if defined(V8_TARGET_ARCH_IA32) |
| 31 | 31 |
| 32 #include "lithium-allocator-inl.h" |
| 32 #include "ia32/lithium-ia32.h" | 33 #include "ia32/lithium-ia32.h" |
| 33 #include "ia32/lithium-codegen-ia32.h" | 34 #include "ia32/lithium-codegen-ia32.h" |
| 34 | 35 |
| 35 namespace v8 { | 36 namespace v8 { |
| 36 namespace internal { | 37 namespace internal { |
| 37 | 38 |
| 38 #define DEFINE_COMPILE(type) \ | 39 #define DEFINE_COMPILE(type) \ |
| 39 void L##type::CompileToNative(LCodeGen* generator) { \ | 40 void L##type::CompileToNative(LCodeGen* generator) { \ |
| 40 generator->Do##type(this); \ | 41 generator->Do##type(this); \ |
| 41 } | 42 } |
| (...skipping 19 matching lines...) Expand all Loading... |
| 61 | 62 |
| 62 | 63 |
| 63 void LOsrEntry::MarkSpilledDoubleRegister(int allocation_index, | 64 void LOsrEntry::MarkSpilledDoubleRegister(int allocation_index, |
| 64 LOperand* spill_operand) { | 65 LOperand* spill_operand) { |
| 65 ASSERT(spill_operand->IsDoubleStackSlot()); | 66 ASSERT(spill_operand->IsDoubleStackSlot()); |
| 66 ASSERT(double_register_spills_[allocation_index] == NULL); | 67 ASSERT(double_register_spills_[allocation_index] == NULL); |
| 67 double_register_spills_[allocation_index] = spill_operand; | 68 double_register_spills_[allocation_index] = spill_operand; |
| 68 } | 69 } |
| 69 | 70 |
| 70 | 71 |
| 72 #ifdef DEBUG |
| 73 void LInstruction::VerifyCall() { |
| 74 // Call instructions can use only fixed registers as |
| 75 // temporaries and outputs because all registers |
| 76 // are blocked by the calling convention. |
| 77 // Inputs can use either fixed register or have a short lifetime (be |
| 78 // used at start of the instruction). |
| 79 ASSERT(Output() == NULL || |
| 80 LUnallocated::cast(Output())->HasFixedPolicy() || |
| 81 !LUnallocated::cast(Output())->HasRegisterPolicy()); |
| 82 for (UseIterator it(this); it.HasNext(); it.Advance()) { |
| 83 LOperand* operand = it.Next(); |
| 84 ASSERT(LUnallocated::cast(operand)->HasFixedPolicy() || |
| 85 LUnallocated::cast(operand)->IsUsedAtStart() || |
| 86 !LUnallocated::cast(operand)->HasRegisterPolicy()); |
| 87 } |
| 88 for (TempIterator it(this); it.HasNext(); it.Advance()) { |
| 89 LOperand* operand = it.Next(); |
| 90 ASSERT(LUnallocated::cast(operand)->HasFixedPolicy() || |
| 91 !LUnallocated::cast(operand)->HasRegisterPolicy()); |
| 92 } |
| 93 } |
| 94 #endif |
| 95 |
| 96 |
| 71 void LInstruction::PrintTo(StringStream* stream) { | 97 void LInstruction::PrintTo(StringStream* stream) { |
| 72 stream->Add("%s ", this->Mnemonic()); | 98 stream->Add("%s ", this->Mnemonic()); |
| 73 if (HasResult()) { | 99 |
| 74 PrintOutputOperandTo(stream); | 100 PrintOutputOperandTo(stream); |
| 75 } | |
| 76 | 101 |
| 77 PrintDataTo(stream); | 102 PrintDataTo(stream); |
| 78 | 103 |
| 79 if (HasEnvironment()) { | 104 if (HasEnvironment()) { |
| 80 stream->Add(" "); | 105 stream->Add(" "); |
| 81 environment()->PrintTo(stream); | 106 environment()->PrintTo(stream); |
| 82 } | 107 } |
| 83 | 108 |
| 84 if (HasPointerMap()) { | 109 if (HasPointerMap()) { |
| 85 stream->Add(" "); | 110 stream->Add(" "); |
| (...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 261 } | 286 } |
| 262 | 287 |
| 263 | 288 |
| 264 void LUnaryMathOperation::PrintDataTo(StringStream* stream) { | 289 void LUnaryMathOperation::PrintDataTo(StringStream* stream) { |
| 265 stream->Add("/%s ", hydrogen()->OpName()); | 290 stream->Add("/%s ", hydrogen()->OpName()); |
| 266 InputAt(0)->PrintTo(stream); | 291 InputAt(0)->PrintTo(stream); |
| 267 } | 292 } |
| 268 | 293 |
| 269 | 294 |
| 270 void LLoadContextSlot::PrintDataTo(StringStream* stream) { | 295 void LLoadContextSlot::PrintDataTo(StringStream* stream) { |
| 271 stream->Add("(%d, %d)", context_chain_length(), slot_index()); | 296 InputAt(0)->PrintTo(stream); |
| 297 stream->Add("[%d]", slot_index()); |
| 298 } |
| 299 |
| 300 |
| 301 void LStoreContextSlot::PrintDataTo(StringStream* stream) { |
| 302 InputAt(0)->PrintTo(stream); |
| 303 stream->Add("[%d] <- ", slot_index()); |
| 304 InputAt(1)->PrintTo(stream); |
| 272 } | 305 } |
| 273 | 306 |
| 274 | 307 |
| 275 void LCallKeyed::PrintDataTo(StringStream* stream) { | 308 void LCallKeyed::PrintDataTo(StringStream* stream) { |
| 276 stream->Add("[ecx] #%d / ", arity()); | 309 stream->Add("[ecx] #%d / ", arity()); |
| 277 } | 310 } |
| 278 | 311 |
| 279 | 312 |
| 280 void LCallNamed::PrintDataTo(StringStream* stream) { | 313 void LCallNamed::PrintDataTo(StringStream* stream) { |
| 281 SmartPointer<char> name_string = name()->ToCString(); | 314 SmartPointer<char> name_string = name()->ToCString(); |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 384 | 417 |
| 385 void LStoreKeyed::PrintDataTo(StringStream* stream) { | 418 void LStoreKeyed::PrintDataTo(StringStream* stream) { |
| 386 object()->PrintTo(stream); | 419 object()->PrintTo(stream); |
| 387 stream->Add("["); | 420 stream->Add("["); |
| 388 key()->PrintTo(stream); | 421 key()->PrintTo(stream); |
| 389 stream->Add("] <- "); | 422 stream->Add("] <- "); |
| 390 value()->PrintTo(stream); | 423 value()->PrintTo(stream); |
| 391 } | 424 } |
| 392 | 425 |
| 393 | 426 |
| 394 int LChunk::AddInstruction(LInstruction* instr, HBasicBlock* block) { | 427 void LChunk::AddInstruction(LInstruction* instr, HBasicBlock* block) { |
| 395 LGap* gap = new LGap(block); | 428 LGap* gap = new LGap(block); |
| 396 int index = -1; | 429 int index = -1; |
| 397 if (instr->IsControl()) { | 430 if (instr->IsControl()) { |
| 398 instructions_.Add(gap); | 431 instructions_.Add(gap); |
| 399 index = instructions_.length(); | 432 index = instructions_.length(); |
| 400 instructions_.Add(instr); | 433 instructions_.Add(instr); |
| 401 } else { | 434 } else { |
| 402 index = instructions_.length(); | 435 index = instructions_.length(); |
| 403 instructions_.Add(instr); | 436 instructions_.Add(instr); |
| 404 instructions_.Add(gap); | 437 instructions_.Add(gap); |
| 405 } | 438 } |
| 406 if (instr->HasPointerMap()) { | 439 if (instr->HasPointerMap()) { |
| 407 pointer_maps_.Add(instr->pointer_map()); | 440 pointer_maps_.Add(instr->pointer_map()); |
| 408 instr->pointer_map()->set_lithium_position(index); | 441 instr->pointer_map()->set_lithium_position(index); |
| 409 } | 442 } |
| 410 return index; | |
| 411 } | 443 } |
| 412 | 444 |
| 413 | 445 |
| 414 LConstantOperand* LChunk::DefineConstantOperand(HConstant* constant) { | 446 LConstantOperand* LChunk::DefineConstantOperand(HConstant* constant) { |
| 415 return LConstantOperand::Create(constant->id()); | 447 return LConstantOperand::Create(constant->id()); |
| 416 } | 448 } |
| 417 | 449 |
| 418 | 450 |
| 419 int LChunk::GetParameterStackSlot(int index) const { | 451 int LChunk::GetParameterStackSlot(int index) const { |
| 420 // The receiver is at index 0, the first parameter at index 1, so we | 452 // The receiver is at index 0, the first parameter at index 1, so we |
| (...skipping 230 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 651 | 683 |
| 652 LInstruction* LChunkBuilder::AssignEnvironment(LInstruction* instr) { | 684 LInstruction* LChunkBuilder::AssignEnvironment(LInstruction* instr) { |
| 653 HEnvironment* hydrogen_env = current_block_->last_environment(); | 685 HEnvironment* hydrogen_env = current_block_->last_environment(); |
| 654 instr->set_environment(CreateEnvironment(hydrogen_env)); | 686 instr->set_environment(CreateEnvironment(hydrogen_env)); |
| 655 return instr; | 687 return instr; |
| 656 } | 688 } |
| 657 | 689 |
| 658 | 690 |
| 659 LInstruction* LChunkBuilder::SetInstructionPendingDeoptimizationEnvironment( | 691 LInstruction* LChunkBuilder::SetInstructionPendingDeoptimizationEnvironment( |
| 660 LInstruction* instr, int ast_id) { | 692 LInstruction* instr, int ast_id) { |
| 661 ASSERT(instructions_pending_deoptimization_environment_ == NULL); | 693 ASSERT(instruction_pending_deoptimization_environment_ == NULL); |
| 662 ASSERT(pending_deoptimization_ast_id_ == AstNode::kNoNumber); | 694 ASSERT(pending_deoptimization_ast_id_ == AstNode::kNoNumber); |
| 663 instructions_pending_deoptimization_environment_ = instr; | 695 instruction_pending_deoptimization_environment_ = instr; |
| 664 pending_deoptimization_ast_id_ = ast_id; | 696 pending_deoptimization_ast_id_ = ast_id; |
| 665 return instr; | 697 return instr; |
| 666 } | 698 } |
| 667 | 699 |
| 668 | 700 |
| 669 void LChunkBuilder::ClearInstructionPendingDeoptimizationEnvironment() { | 701 void LChunkBuilder::ClearInstructionPendingDeoptimizationEnvironment() { |
| 670 instructions_pending_deoptimization_environment_ = NULL; | 702 instruction_pending_deoptimization_environment_ = NULL; |
| 671 pending_deoptimization_ast_id_ = AstNode::kNoNumber; | 703 pending_deoptimization_ast_id_ = AstNode::kNoNumber; |
| 672 } | 704 } |
| 673 | 705 |
| 674 | 706 |
| 675 LInstruction* LChunkBuilder::MarkAsCall(LInstruction* instr, | 707 LInstruction* LChunkBuilder::MarkAsCall(LInstruction* instr, |
| 676 HInstruction* hinstr, | 708 HInstruction* hinstr, |
| 677 CanDeoptimize can_deoptimize) { | 709 CanDeoptimize can_deoptimize) { |
| 678 allocator_->MarkAsCall(); | 710 #ifdef DEBUG |
| 711 instr->VerifyCall(); |
| 712 #endif |
| 713 instr->MarkAsCall(); |
| 679 instr = AssignPointerMap(instr); | 714 instr = AssignPointerMap(instr); |
| 680 | 715 |
| 681 if (hinstr->HasSideEffects()) { | 716 if (hinstr->HasSideEffects()) { |
| 682 ASSERT(hinstr->next()->IsSimulate()); | 717 ASSERT(hinstr->next()->IsSimulate()); |
| 683 HSimulate* sim = HSimulate::cast(hinstr->next()); | 718 HSimulate* sim = HSimulate::cast(hinstr->next()); |
| 684 instr = SetInstructionPendingDeoptimizationEnvironment( | 719 instr = SetInstructionPendingDeoptimizationEnvironment( |
| 685 instr, sim->ast_id()); | 720 instr, sim->ast_id()); |
| 686 } | 721 } |
| 687 | 722 |
| 688 // If instruction does not have side-effects lazy deoptimization | 723 // If instruction does not have side-effects lazy deoptimization |
| 689 // after the call will try to deoptimize to the point before the call. | 724 // after the call will try to deoptimize to the point before the call. |
| 690 // Thus we still need to attach environment to this call even if | 725 // Thus we still need to attach environment to this call even if |
| 691 // call sequence can not deoptimize eagerly. | 726 // call sequence can not deoptimize eagerly. |
| 692 bool needs_environment = | 727 bool needs_environment = |
| 693 (can_deoptimize == CAN_DEOPTIMIZE_EAGERLY) || !hinstr->HasSideEffects(); | 728 (can_deoptimize == CAN_DEOPTIMIZE_EAGERLY) || !hinstr->HasSideEffects(); |
| 694 if (needs_environment && !instr->HasEnvironment()) { | 729 if (needs_environment && !instr->HasEnvironment()) { |
| 695 instr = AssignEnvironment(instr); | 730 instr = AssignEnvironment(instr); |
| 696 } | 731 } |
| 697 | 732 |
| 698 return instr; | 733 return instr; |
| 699 } | 734 } |
| 700 | 735 |
| 701 | 736 |
| 702 LInstruction* LChunkBuilder::MarkAsSaveDoubles(LInstruction* instr) { | 737 LInstruction* LChunkBuilder::MarkAsSaveDoubles(LInstruction* instr) { |
| 703 allocator_->MarkAsSaveDoubles(); | 738 instr->MarkAsSaveDoubles(); |
| 704 return instr; | 739 return instr; |
| 705 } | 740 } |
| 706 | 741 |
| 707 | 742 |
| 708 LInstruction* LChunkBuilder::AssignPointerMap(LInstruction* instr) { | 743 LInstruction* LChunkBuilder::AssignPointerMap(LInstruction* instr) { |
| 709 ASSERT(!instr->HasPointerMap()); | 744 ASSERT(!instr->HasPointerMap()); |
| 710 instr->set_pointer_map(new LPointerMap(position_)); | 745 instr->set_pointer_map(new LPointerMap(position_)); |
| 711 return instr; | 746 return instr; |
| 712 } | 747 } |
| 713 | 748 |
| (...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 902 } | 937 } |
| 903 block->set_argument_count(argument_count_); | 938 block->set_argument_count(argument_count_); |
| 904 next_block_ = NULL; | 939 next_block_ = NULL; |
| 905 current_block_ = NULL; | 940 current_block_ = NULL; |
| 906 } | 941 } |
| 907 | 942 |
| 908 | 943 |
| 909 void LChunkBuilder::VisitInstruction(HInstruction* current) { | 944 void LChunkBuilder::VisitInstruction(HInstruction* current) { |
| 910 HInstruction* old_current = current_instruction_; | 945 HInstruction* old_current = current_instruction_; |
| 911 current_instruction_ = current; | 946 current_instruction_ = current; |
| 912 allocator_->BeginInstruction(); | |
| 913 if (current->has_position()) position_ = current->position(); | 947 if (current->has_position()) position_ = current->position(); |
| 914 LInstruction* instr = current->CompileToLithium(this); | 948 LInstruction* instr = current->CompileToLithium(this); |
| 915 | 949 |
| 916 if (instr != NULL) { | 950 if (instr != NULL) { |
| 917 if (FLAG_stress_pointer_maps && !instr->HasPointerMap()) { | 951 if (FLAG_stress_pointer_maps && !instr->HasPointerMap()) { |
| 918 instr = AssignPointerMap(instr); | 952 instr = AssignPointerMap(instr); |
| 919 } | 953 } |
| 920 if (FLAG_stress_environments && !instr->HasEnvironment()) { | 954 if (FLAG_stress_environments && !instr->HasEnvironment()) { |
| 921 instr = AssignEnvironment(instr); | 955 instr = AssignEnvironment(instr); |
| 922 } | 956 } |
| 923 if (current->IsTest() && !instr->IsGoto()) { | 957 if (current->IsTest() && !instr->IsGoto()) { |
| 924 ASSERT(instr->IsControl()); | 958 ASSERT(instr->IsControl()); |
| 925 HTest* test = HTest::cast(current); | 959 HTest* test = HTest::cast(current); |
| 926 instr->set_hydrogen_value(test->value()); | 960 instr->set_hydrogen_value(test->value()); |
| 927 HBasicBlock* first = test->FirstSuccessor(); | 961 HBasicBlock* first = test->FirstSuccessor(); |
| 928 HBasicBlock* second = test->SecondSuccessor(); | 962 HBasicBlock* second = test->SecondSuccessor(); |
| 929 ASSERT(first != NULL && second != NULL); | 963 ASSERT(first != NULL && second != NULL); |
| 930 instr->SetBranchTargets(first->block_id(), second->block_id()); | 964 instr->SetBranchTargets(first->block_id(), second->block_id()); |
| 931 } else { | 965 } else { |
| 932 instr->set_hydrogen_value(current); | 966 instr->set_hydrogen_value(current); |
| 933 } | 967 } |
| 934 | 968 |
| 935 int index = chunk_->AddInstruction(instr, current_block_); | 969 chunk_->AddInstruction(instr, current_block_); |
| 936 allocator_->SummarizeInstruction(index); | |
| 937 } else { | |
| 938 // This instruction should be omitted. | |
| 939 allocator_->OmitInstruction(); | |
| 940 } | 970 } |
| 941 current_instruction_ = old_current; | 971 current_instruction_ = old_current; |
| 942 } | 972 } |
| 943 | 973 |
| 944 | 974 |
| 945 LEnvironment* LChunkBuilder::CreateEnvironment(HEnvironment* hydrogen_env) { | 975 LEnvironment* LChunkBuilder::CreateEnvironment(HEnvironment* hydrogen_env) { |
| 946 if (hydrogen_env == NULL) return NULL; | 976 if (hydrogen_env == NULL) return NULL; |
| 947 | 977 |
| 948 LEnvironment* outer = CreateEnvironment(hydrogen_env->outer()); | 978 LEnvironment* outer = CreateEnvironment(hydrogen_env->outer()); |
| 949 int ast_id = hydrogen_env->ast_id(); | 979 int ast_id = hydrogen_env->ast_id(); |
| (...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1061 } else if (v->IsInstanceOf()) { | 1091 } else if (v->IsInstanceOf()) { |
| 1062 HInstanceOf* instance_of = HInstanceOf::cast(v); | 1092 HInstanceOf* instance_of = HInstanceOf::cast(v); |
| 1063 LInstanceOfAndBranch* result = | 1093 LInstanceOfAndBranch* result = |
| 1064 new LInstanceOfAndBranch( | 1094 new LInstanceOfAndBranch( |
| 1065 UseFixed(instance_of->left(), InstanceofStub::left()), | 1095 UseFixed(instance_of->left(), InstanceofStub::left()), |
| 1066 UseFixed(instance_of->right(), InstanceofStub::right())); | 1096 UseFixed(instance_of->right(), InstanceofStub::right())); |
| 1067 return MarkAsCall(result, instr); | 1097 return MarkAsCall(result, instr); |
| 1068 } else if (v->IsTypeofIs()) { | 1098 } else if (v->IsTypeofIs()) { |
| 1069 HTypeofIs* typeof_is = HTypeofIs::cast(v); | 1099 HTypeofIs* typeof_is = HTypeofIs::cast(v); |
| 1070 return new LTypeofIsAndBranch(UseTempRegister(typeof_is->value())); | 1100 return new LTypeofIsAndBranch(UseTempRegister(typeof_is->value())); |
| 1101 } else if (v->IsIsConstructCall()) { |
| 1102 return new LIsConstructCallAndBranch(TempRegister()); |
| 1071 } else { | 1103 } else { |
| 1072 if (v->IsConstant()) { | 1104 if (v->IsConstant()) { |
| 1073 if (HConstant::cast(v)->handle()->IsTrue()) { | 1105 if (HConstant::cast(v)->handle()->IsTrue()) { |
| 1074 return new LGoto(instr->FirstSuccessor()->block_id()); | 1106 return new LGoto(instr->FirstSuccessor()->block_id()); |
| 1075 } else if (HConstant::cast(v)->handle()->IsFalse()) { | 1107 } else if (HConstant::cast(v)->handle()->IsFalse()) { |
| 1076 return new LGoto(instr->SecondSuccessor()->block_id()); | 1108 return new LGoto(instr->SecondSuccessor()->block_id()); |
| 1077 } | 1109 } |
| 1078 } | 1110 } |
| 1079 Abort("Undefined compare before branch"); | 1111 Abort("Undefined compare before branch"); |
| 1080 return NULL; | 1112 return NULL; |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1133 } | 1165 } |
| 1134 | 1166 |
| 1135 | 1167 |
| 1136 LInstruction* LChunkBuilder::DoPushArgument(HPushArgument* instr) { | 1168 LInstruction* LChunkBuilder::DoPushArgument(HPushArgument* instr) { |
| 1137 ++argument_count_; | 1169 ++argument_count_; |
| 1138 LOperand* argument = UseOrConstant(instr->argument()); | 1170 LOperand* argument = UseOrConstant(instr->argument()); |
| 1139 return new LPushArgument(argument); | 1171 return new LPushArgument(argument); |
| 1140 } | 1172 } |
| 1141 | 1173 |
| 1142 | 1174 |
| 1175 LInstruction* LChunkBuilder::DoContext(HContext* instr) { |
| 1176 return DefineAsRegister(new LContext); |
| 1177 } |
| 1178 |
| 1179 |
| 1180 LInstruction* LChunkBuilder::DoOuterContext(HOuterContext* instr) { |
| 1181 LOperand* context = UseRegisterAtStart(instr->value()); |
| 1182 return DefineAsRegister(new LOuterContext(context)); |
| 1183 } |
| 1184 |
| 1185 |
| 1143 LInstruction* LChunkBuilder::DoGlobalObject(HGlobalObject* instr) { | 1186 LInstruction* LChunkBuilder::DoGlobalObject(HGlobalObject* instr) { |
| 1144 return DefineAsRegister(new LGlobalObject); | 1187 LOperand* context = UseRegisterAtStart(instr->value()); |
| 1188 return DefineAsRegister(new LGlobalObject(context)); |
| 1145 } | 1189 } |
| 1146 | 1190 |
| 1147 | 1191 |
| 1148 LInstruction* LChunkBuilder::DoGlobalReceiver(HGlobalReceiver* instr) { | 1192 LInstruction* LChunkBuilder::DoGlobalReceiver(HGlobalReceiver* instr) { |
| 1149 return DefineAsRegister(new LGlobalReceiver); | 1193 LOperand* global_object = UseRegisterAtStart(instr->value()); |
| 1194 return DefineAsRegister(new LGlobalReceiver(global_object)); |
| 1150 } | 1195 } |
| 1151 | 1196 |
| 1152 | 1197 |
| 1153 LInstruction* LChunkBuilder::DoCallConstantFunction( | 1198 LInstruction* LChunkBuilder::DoCallConstantFunction( |
| 1154 HCallConstantFunction* instr) { | 1199 HCallConstantFunction* instr) { |
| 1155 argument_count_ -= instr->argument_count(); | 1200 argument_count_ -= instr->argument_count(); |
| 1156 return MarkAsCall(DefineFixed(new LCallConstantFunction, eax), instr); | 1201 return MarkAsCall(DefineFixed(new LCallConstantFunction, eax), instr); |
| 1157 } | 1202 } |
| 1158 | 1203 |
| 1159 | 1204 |
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1270 } | 1315 } |
| 1271 | 1316 |
| 1272 | 1317 |
| 1273 LInstruction* LChunkBuilder::DoDiv(HDiv* instr) { | 1318 LInstruction* LChunkBuilder::DoDiv(HDiv* instr) { |
| 1274 if (instr->representation().IsDouble()) { | 1319 if (instr->representation().IsDouble()) { |
| 1275 return DoArithmeticD(Token::DIV, instr); | 1320 return DoArithmeticD(Token::DIV, instr); |
| 1276 } else if (instr->representation().IsInteger32()) { | 1321 } else if (instr->representation().IsInteger32()) { |
| 1277 // The temporary operand is necessary to ensure that right is not allocated | 1322 // The temporary operand is necessary to ensure that right is not allocated |
| 1278 // into edx. | 1323 // into edx. |
| 1279 LOperand* temp = FixedTemp(edx); | 1324 LOperand* temp = FixedTemp(edx); |
| 1280 LOperand* value = UseFixed(instr->left(), eax); | 1325 LOperand* dividend = UseFixed(instr->left(), eax); |
| 1281 LOperand* divisor = UseRegister(instr->right()); | 1326 LOperand* divisor = UseRegister(instr->right()); |
| 1282 LDivI* result = new LDivI(value, divisor, temp); | 1327 LDivI* result = new LDivI(dividend, divisor, temp); |
| 1283 return AssignEnvironment(DefineFixed(result, eax)); | 1328 return AssignEnvironment(DefineFixed(result, eax)); |
| 1284 } else { | 1329 } else { |
| 1285 ASSERT(instr->representation().IsTagged()); | 1330 ASSERT(instr->representation().IsTagged()); |
| 1286 return DoArithmeticT(Token::DIV, instr); | 1331 return DoArithmeticT(Token::DIV, instr); |
| 1287 } | 1332 } |
| 1288 } | 1333 } |
| 1289 | 1334 |
| 1290 | 1335 |
| 1291 LInstruction* LChunkBuilder::DoMod(HMod* instr) { | 1336 LInstruction* LChunkBuilder::DoMod(HMod* instr) { |
| 1292 if (instr->representation().IsInteger32()) { | 1337 if (instr->representation().IsInteger32()) { |
| (...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1500 return AssignEnvironment(DefineSameAsFirst(result)); | 1545 return AssignEnvironment(DefineSameAsFirst(result)); |
| 1501 } | 1546 } |
| 1502 | 1547 |
| 1503 | 1548 |
| 1504 LInstruction* LChunkBuilder::DoBoundsCheck(HBoundsCheck* instr) { | 1549 LInstruction* LChunkBuilder::DoBoundsCheck(HBoundsCheck* instr) { |
| 1505 return AssignEnvironment(new LBoundsCheck(UseRegisterAtStart(instr->index()), | 1550 return AssignEnvironment(new LBoundsCheck(UseRegisterAtStart(instr->index()), |
| 1506 Use(instr->length()))); | 1551 Use(instr->length()))); |
| 1507 } | 1552 } |
| 1508 | 1553 |
| 1509 | 1554 |
| 1555 LInstruction* LChunkBuilder::DoAbnormalExit(HAbnormalExit* instr) { |
| 1556 // The control instruction marking the end of a block that completed |
| 1557 // abruptly (e.g., threw an exception). There is nothing specific to do. |
| 1558 return NULL; |
| 1559 } |
| 1560 |
| 1561 |
| 1510 LInstruction* LChunkBuilder::DoThrow(HThrow* instr) { | 1562 LInstruction* LChunkBuilder::DoThrow(HThrow* instr) { |
| 1511 LOperand* value = UseFixed(instr->value(), eax); | 1563 LOperand* value = UseFixed(instr->value(), eax); |
| 1512 return MarkAsCall(new LThrow(value), instr); | 1564 return MarkAsCall(new LThrow(value), instr); |
| 1513 } | 1565 } |
| 1514 | 1566 |
| 1515 | 1567 |
| 1516 LInstruction* LChunkBuilder::DoChange(HChange* instr) { | 1568 LInstruction* LChunkBuilder::DoChange(HChange* instr) { |
| 1517 Representation from = instr->from(); | 1569 Representation from = instr->from(); |
| 1518 Representation to = instr->to(); | 1570 Representation to = instr->to(); |
| 1519 if (from.IsTagged()) { | 1571 if (from.IsTagged()) { |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1616 | 1668 |
| 1617 | 1669 |
| 1618 LInstruction* LChunkBuilder::DoReturn(HReturn* instr) { | 1670 LInstruction* LChunkBuilder::DoReturn(HReturn* instr) { |
| 1619 return new LReturn(UseFixed(instr->value(), eax)); | 1671 return new LReturn(UseFixed(instr->value(), eax)); |
| 1620 } | 1672 } |
| 1621 | 1673 |
| 1622 | 1674 |
| 1623 LInstruction* LChunkBuilder::DoConstant(HConstant* instr) { | 1675 LInstruction* LChunkBuilder::DoConstant(HConstant* instr) { |
| 1624 Representation r = instr->representation(); | 1676 Representation r = instr->representation(); |
| 1625 if (r.IsInteger32()) { | 1677 if (r.IsInteger32()) { |
| 1626 int32_t value = instr->Integer32Value(); | 1678 return DefineAsRegister(new LConstantI); |
| 1627 return DefineAsRegister(new LConstantI(value)); | |
| 1628 } else if (r.IsDouble()) { | 1679 } else if (r.IsDouble()) { |
| 1629 double value = instr->DoubleValue(); | 1680 double value = instr->DoubleValue(); |
| 1630 return DefineAsRegister(new LConstantD(value)); | 1681 LOperand* temp = (BitCast<uint64_t, double>(value) != 0) |
| 1682 ? TempRegister() |
| 1683 : NULL; |
| 1684 return DefineAsRegister(new LConstantD(temp)); |
| 1631 } else if (r.IsTagged()) { | 1685 } else if (r.IsTagged()) { |
| 1632 return DefineAsRegister(new LConstantT(instr->handle())); | 1686 return DefineAsRegister(new LConstantT); |
| 1633 } else { | 1687 } else { |
| 1634 UNREACHABLE(); | 1688 UNREACHABLE(); |
| 1635 return NULL; | 1689 return NULL; |
| 1636 } | 1690 } |
| 1637 } | 1691 } |
| 1638 | 1692 |
| 1639 | 1693 |
| 1640 LInstruction* LChunkBuilder::DoLoadGlobal(HLoadGlobal* instr) { | 1694 LInstruction* LChunkBuilder::DoLoadGlobal(HLoadGlobal* instr) { |
| 1641 LLoadGlobal* result = new LLoadGlobal; | 1695 LLoadGlobal* result = new LLoadGlobal; |
| 1642 return instr->check_hole_value() | 1696 return instr->check_hole_value() |
| 1643 ? AssignEnvironment(DefineAsRegister(result)) | 1697 ? AssignEnvironment(DefineAsRegister(result)) |
| 1644 : DefineAsRegister(result); | 1698 : DefineAsRegister(result); |
| 1645 } | 1699 } |
| 1646 | 1700 |
| 1647 | 1701 |
| 1648 LInstruction* LChunkBuilder::DoStoreGlobal(HStoreGlobal* instr) { | 1702 LInstruction* LChunkBuilder::DoStoreGlobal(HStoreGlobal* instr) { |
| 1649 return new LStoreGlobal(UseRegisterAtStart(instr->value())); | 1703 LStoreGlobal* result = new LStoreGlobal(UseRegisterAtStart(instr->value())); |
| 1704 return instr->check_hole_value() ? AssignEnvironment(result) : result; |
| 1650 } | 1705 } |
| 1651 | 1706 |
| 1652 | 1707 |
| 1653 LInstruction* LChunkBuilder::DoLoadContextSlot(HLoadContextSlot* instr) { | 1708 LInstruction* LChunkBuilder::DoLoadContextSlot(HLoadContextSlot* instr) { |
| 1654 return DefineAsRegister(new LLoadContextSlot); | 1709 LOperand* context = UseRegisterAtStart(instr->value()); |
| 1710 return DefineAsRegister(new LLoadContextSlot(context)); |
| 1711 } |
| 1712 |
| 1713 |
| 1714 LInstruction* LChunkBuilder::DoStoreContextSlot(HStoreContextSlot* instr) { |
| 1715 LOperand* context; |
| 1716 LOperand* value; |
| 1717 LOperand* temp; |
| 1718 if (instr->NeedsWriteBarrier()) { |
| 1719 context = UseTempRegister(instr->context()); |
| 1720 value = UseTempRegister(instr->value()); |
| 1721 temp = TempRegister(); |
| 1722 } else { |
| 1723 context = UseRegister(instr->context()); |
| 1724 value = UseRegister(instr->value()); |
| 1725 temp = NULL; |
| 1726 } |
| 1727 return new LStoreContextSlot(context, value, temp); |
| 1655 } | 1728 } |
| 1656 | 1729 |
| 1657 | 1730 |
| 1658 LInstruction* LChunkBuilder::DoLoadNamedField(HLoadNamedField* instr) { | 1731 LInstruction* LChunkBuilder::DoLoadNamedField(HLoadNamedField* instr) { |
| 1659 ASSERT(instr->representation().IsTagged()); | 1732 ASSERT(instr->representation().IsTagged()); |
| 1660 LOperand* obj = UseRegisterAtStart(instr->object()); | 1733 LOperand* obj = UseRegisterAtStart(instr->object()); |
| 1661 return DefineAsRegister(new LLoadNamedField(obj)); | 1734 return DefineAsRegister(new LLoadNamedField(obj)); |
| 1662 } | 1735 } |
| 1663 | 1736 |
| 1664 | 1737 |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1742 ? UseTempRegister(instr->object()) | 1815 ? UseTempRegister(instr->object()) |
| 1743 : UseRegisterAtStart(instr->object()); | 1816 : UseRegisterAtStart(instr->object()); |
| 1744 | 1817 |
| 1745 LOperand* val = needs_write_barrier | 1818 LOperand* val = needs_write_barrier |
| 1746 ? UseTempRegister(instr->value()) | 1819 ? UseTempRegister(instr->value()) |
| 1747 : UseRegister(instr->value()); | 1820 : UseRegister(instr->value()); |
| 1748 | 1821 |
| 1749 // We only need a scratch register if we have a write barrier or we | 1822 // We only need a scratch register if we have a write barrier or we |
| 1750 // have a store into the properties array (not in-object-property). | 1823 // have a store into the properties array (not in-object-property). |
| 1751 LOperand* temp = (!instr->is_in_object() || needs_write_barrier) | 1824 LOperand* temp = (!instr->is_in_object() || needs_write_barrier) |
| 1752 ? TempRegister() : NULL; | 1825 ? TempRegister() |
| 1826 : NULL; |
| 1753 | 1827 |
| 1754 return new LStoreNamedField(obj, val, temp); | 1828 return new LStoreNamedField(obj, val, temp); |
| 1755 } | 1829 } |
| 1756 | 1830 |
| 1757 | 1831 |
| 1758 LInstruction* LChunkBuilder::DoStoreNamedGeneric(HStoreNamedGeneric* instr) { | 1832 LInstruction* LChunkBuilder::DoStoreNamedGeneric(HStoreNamedGeneric* instr) { |
| 1759 LOperand* obj = UseFixed(instr->object(), edx); | 1833 LOperand* obj = UseFixed(instr->object(), edx); |
| 1760 LOperand* val = UseFixed(instr->value(), eax); | 1834 LOperand* val = UseFixed(instr->value(), eax); |
| 1761 | 1835 |
| 1762 LStoreNamedGeneric* result = new LStoreNamedGeneric(obj, val); | 1836 LStoreNamedGeneric* result = new LStoreNamedGeneric(obj, val); |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1849 LInstruction* LChunkBuilder::DoTypeof(HTypeof* instr) { | 1923 LInstruction* LChunkBuilder::DoTypeof(HTypeof* instr) { |
| 1850 LTypeof* result = new LTypeof(UseAtStart(instr->value())); | 1924 LTypeof* result = new LTypeof(UseAtStart(instr->value())); |
| 1851 return MarkAsCall(DefineFixed(result, eax), instr); | 1925 return MarkAsCall(DefineFixed(result, eax), instr); |
| 1852 } | 1926 } |
| 1853 | 1927 |
| 1854 | 1928 |
| 1855 LInstruction* LChunkBuilder::DoTypeofIs(HTypeofIs* instr) { | 1929 LInstruction* LChunkBuilder::DoTypeofIs(HTypeofIs* instr) { |
| 1856 return DefineSameAsFirst(new LTypeofIs(UseRegister(instr->value()))); | 1930 return DefineSameAsFirst(new LTypeofIs(UseRegister(instr->value()))); |
| 1857 } | 1931 } |
| 1858 | 1932 |
| 1933 |
| 1934 LInstruction* LChunkBuilder::DoIsConstructCall(HIsConstructCall* instr) { |
| 1935 return DefineAsRegister(new LIsConstructCall); |
| 1936 } |
| 1937 |
| 1938 |
| 1859 LInstruction* LChunkBuilder::DoSimulate(HSimulate* instr) { | 1939 LInstruction* LChunkBuilder::DoSimulate(HSimulate* instr) { |
| 1860 HEnvironment* env = current_block_->last_environment(); | 1940 HEnvironment* env = current_block_->last_environment(); |
| 1861 ASSERT(env != NULL); | 1941 ASSERT(env != NULL); |
| 1862 | 1942 |
| 1863 env->set_ast_id(instr->ast_id()); | 1943 env->set_ast_id(instr->ast_id()); |
| 1864 | 1944 |
| 1865 env->Drop(instr->pop_count()); | 1945 env->Drop(instr->pop_count()); |
| 1866 for (int i = 0; i < instr->values()->length(); ++i) { | 1946 for (int i = 0; i < instr->values()->length(); ++i) { |
| 1867 HValue* value = instr->values()->at(i); | 1947 HValue* value = instr->values()->at(i); |
| 1868 if (instr->HasAssignedIndexAt(i)) { | 1948 if (instr->HasAssignedIndexAt(i)) { |
| 1869 env->Bind(instr->GetAssignedIndexAt(i), value); | 1949 env->Bind(instr->GetAssignedIndexAt(i), value); |
| 1870 } else { | 1950 } else { |
| 1871 env->Push(value); | 1951 env->Push(value); |
| 1872 } | 1952 } |
| 1873 } | 1953 } |
| 1874 ASSERT(env->length() == instr->environment_length()); | 1954 ASSERT(env->length() == instr->environment_length()); |
| 1875 | 1955 |
| 1876 // If there is an instruction pending deoptimization environment create a | 1956 // If there is an instruction pending deoptimization environment create a |
| 1877 // lazy bailout instruction to capture the environment. | 1957 // lazy bailout instruction to capture the environment. |
| 1878 if (pending_deoptimization_ast_id_ == instr->ast_id()) { | 1958 if (pending_deoptimization_ast_id_ != AstNode::kNoNumber) { |
| 1959 ASSERT(pending_deoptimization_ast_id_ == instr->ast_id()); |
| 1879 LLazyBailout* lazy_bailout = new LLazyBailout; | 1960 LLazyBailout* lazy_bailout = new LLazyBailout; |
| 1880 LInstruction* result = AssignEnvironment(lazy_bailout); | 1961 LInstruction* result = AssignEnvironment(lazy_bailout); |
| 1881 instructions_pending_deoptimization_environment_-> | 1962 instruction_pending_deoptimization_environment_-> |
| 1882 set_deoptimization_environment(result->environment()); | 1963 set_deoptimization_environment(result->environment()); |
| 1883 ClearInstructionPendingDeoptimizationEnvironment(); | 1964 ClearInstructionPendingDeoptimizationEnvironment(); |
| 1884 return result; | 1965 return result; |
| 1885 } | 1966 } |
| 1886 | 1967 |
| 1887 return NULL; | 1968 return NULL; |
| 1888 } | 1969 } |
| 1889 | 1970 |
| 1890 | 1971 |
| 1891 LInstruction* LChunkBuilder::DoStackCheck(HStackCheck* instr) { | 1972 LInstruction* LChunkBuilder::DoStackCheck(HStackCheck* instr) { |
| (...skipping 17 matching lines...) Expand all Loading... |
| 1909 LInstruction* LChunkBuilder::DoLeaveInlined(HLeaveInlined* instr) { | 1990 LInstruction* LChunkBuilder::DoLeaveInlined(HLeaveInlined* instr) { |
| 1910 HEnvironment* outer = current_block_->last_environment()->outer(); | 1991 HEnvironment* outer = current_block_->last_environment()->outer(); |
| 1911 current_block_->UpdateEnvironment(outer); | 1992 current_block_->UpdateEnvironment(outer); |
| 1912 return NULL; | 1993 return NULL; |
| 1913 } | 1994 } |
| 1914 | 1995 |
| 1915 | 1996 |
| 1916 } } // namespace v8::internal | 1997 } } // namespace v8::internal |
| 1917 | 1998 |
| 1918 #endif // V8_TARGET_ARCH_IA32 | 1999 #endif // V8_TARGET_ARCH_IA32 |
| OLD | NEW |