| 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 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 71 | 71 |
| 72 #ifdef DEBUG | 72 #ifdef DEBUG |
| 73 void LInstruction::VerifyCall() { | 73 void LInstruction::VerifyCall() { |
| 74 // Call instructions can use only fixed registers as temporaries and | 74 // Call instructions can use only fixed registers as temporaries and |
| 75 // outputs because all registers are blocked by the calling convention. | 75 // outputs because all registers are blocked by the calling convention. |
| 76 // Inputs operands must use a fixed register or use-at-start policy or | 76 // Inputs operands must use a fixed register or use-at-start policy or |
| 77 // a non-register policy. | 77 // a non-register policy. |
| 78 ASSERT(Output() == NULL || | 78 ASSERT(Output() == NULL || |
| 79 LUnallocated::cast(Output())->HasFixedPolicy() || | 79 LUnallocated::cast(Output())->HasFixedPolicy() || |
| 80 !LUnallocated::cast(Output())->HasRegisterPolicy()); | 80 !LUnallocated::cast(Output())->HasRegisterPolicy()); |
| 81 for (UseIterator it(this); it.HasNext(); it.Advance()) { | 81 for (UseIterator it(this); !it.Done(); it.Advance()) { |
| 82 LUnallocated* operand = LUnallocated::cast(it.Next()); | 82 LUnallocated* operand = LUnallocated::cast(it.Current()); |
| 83 ASSERT(operand->HasFixedPolicy() || | 83 ASSERT(operand->HasFixedPolicy() || |
| 84 operand->IsUsedAtStart()); | 84 operand->IsUsedAtStart()); |
| 85 } | 85 } |
| 86 for (TempIterator it(this); it.HasNext(); it.Advance()) { | 86 for (TempIterator it(this); !it.Done(); it.Advance()) { |
| 87 LUnallocated* operand = LUnallocated::cast(it.Next()); | 87 LUnallocated* operand = LUnallocated::cast(it.Current()); |
| 88 ASSERT(operand->HasFixedPolicy() ||!operand->HasRegisterPolicy()); | 88 ASSERT(operand->HasFixedPolicy() ||!operand->HasRegisterPolicy()); |
| 89 } | 89 } |
| 90 } | 90 } |
| 91 #endif | 91 #endif |
| 92 | 92 |
| 93 | 93 |
| 94 void LInstruction::PrintTo(StringStream* stream) { | 94 void LInstruction::PrintTo(StringStream* stream) { |
| 95 stream->Add("%s ", this->Mnemonic()); | 95 stream->Add("%s ", this->Mnemonic()); |
| 96 | 96 |
| 97 PrintOutputOperandTo(stream); | 97 PrintOutputOperandTo(stream); |
| 98 | 98 |
| 99 PrintDataTo(stream); | 99 PrintDataTo(stream); |
| 100 | 100 |
| 101 if (HasEnvironment()) { | 101 if (HasEnvironment()) { |
| 102 stream->Add(" "); | 102 stream->Add(" "); |
| 103 environment()->PrintTo(stream); | 103 environment()->PrintTo(stream); |
| 104 } | 104 } |
| 105 | 105 |
| 106 if (HasPointerMap()) { | 106 if (HasPointerMap()) { |
| 107 stream->Add(" "); | 107 stream->Add(" "); |
| 108 pointer_map()->PrintTo(stream); | 108 pointer_map()->PrintTo(stream); |
| 109 } | 109 } |
| 110 } | 110 } |
| 111 | 111 |
| 112 | 112 |
| 113 template<int R, int I, int T> | 113 template<int R, int I, int T> |
| 114 void LTemplateInstruction<R, I, T>::PrintDataTo(StringStream* stream) { | 114 void LTemplateInstruction<R, I, T>::PrintDataTo(StringStream* stream) { |
| 115 stream->Add("= "); | 115 stream->Add("= "); |
| 116 inputs_.PrintOperandsTo(stream); | 116 for (int i = 0; i < inputs_.length(); i++) { |
| 117 if (i > 0) stream->Add(" "); |
| 118 inputs_[i]->PrintTo(stream); |
| 119 } |
| 117 } | 120 } |
| 118 | 121 |
| 119 | 122 |
| 120 template<int R, int I, int T> | 123 template<int R, int I, int T> |
| 121 void LTemplateInstruction<R, I, T>::PrintOutputOperandTo(StringStream* stream) { | 124 void LTemplateInstruction<R, I, T>::PrintOutputOperandTo(StringStream* stream) { |
| 122 results_.PrintOperandsTo(stream); | 125 for (int i = 0; i < results_.length(); i++) { |
| 123 } | |
| 124 | |
| 125 | |
| 126 template<typename T, int N> | |
| 127 void OperandContainer<T, N>::PrintOperandsTo(StringStream* stream) { | |
| 128 for (int i = 0; i < N; i++) { | |
| 129 if (i > 0) stream->Add(" "); | 126 if (i > 0) stream->Add(" "); |
| 130 elems_[i]->PrintTo(stream); | 127 results_[i]->PrintTo(stream); |
| 131 } | 128 } |
| 132 } | 129 } |
| 133 | 130 |
| 134 | 131 |
| 135 void LLabel::PrintDataTo(StringStream* stream) { | 132 void LLabel::PrintDataTo(StringStream* stream) { |
| 136 LGap::PrintDataTo(stream); | 133 LGap::PrintDataTo(stream); |
| 137 LLabel* rep = replacement(); | 134 LLabel* rep = replacement(); |
| 138 if (rep != NULL) { | 135 if (rep != NULL) { |
| 139 stream->Add(" Dead block replaced with B%d", rep->block_id()); | 136 stream->Add(" Dead block replaced with B%d", rep->block_id()); |
| 140 } | 137 } |
| (...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 263 void LClassOfTestAndBranch::PrintDataTo(StringStream* stream) { | 260 void LClassOfTestAndBranch::PrintDataTo(StringStream* stream) { |
| 264 stream->Add("if class_of_test("); | 261 stream->Add("if class_of_test("); |
| 265 InputAt(0)->PrintTo(stream); | 262 InputAt(0)->PrintTo(stream); |
| 266 stream->Add(", \"%o\") then B%d else B%d", | 263 stream->Add(", \"%o\") then B%d else B%d", |
| 267 *hydrogen()->class_name(), | 264 *hydrogen()->class_name(), |
| 268 true_block_id(), | 265 true_block_id(), |
| 269 false_block_id()); | 266 false_block_id()); |
| 270 } | 267 } |
| 271 | 268 |
| 272 | 269 |
| 273 void LTypeofIs::PrintDataTo(StringStream* stream) { | |
| 274 InputAt(0)->PrintTo(stream); | |
| 275 stream->Add(" == \"%s\"", *hydrogen()->type_literal()->ToCString()); | |
| 276 } | |
| 277 | |
| 278 | |
| 279 void LTypeofIsAndBranch::PrintDataTo(StringStream* stream) { | 270 void LTypeofIsAndBranch::PrintDataTo(StringStream* stream) { |
| 280 stream->Add("if typeof "); | 271 stream->Add("if typeof "); |
| 281 InputAt(0)->PrintTo(stream); | 272 InputAt(0)->PrintTo(stream); |
| 282 stream->Add(" == \"%s\" then B%d else B%d", | 273 stream->Add(" == \"%s\" then B%d else B%d", |
| 283 *hydrogen()->type_literal()->ToCString(), | 274 *hydrogen()->type_literal()->ToCString(), |
| 284 true_block_id(), false_block_id()); | 275 true_block_id(), false_block_id()); |
| 285 } | 276 } |
| 286 | 277 |
| 287 | 278 |
| 288 void LCallConstantFunction::PrintDataTo(StringStream* stream) { | 279 void LCallConstantFunction::PrintDataTo(StringStream* stream) { |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 338 } | 329 } |
| 339 | 330 |
| 340 | 331 |
| 341 void LCallNew::PrintDataTo(StringStream* stream) { | 332 void LCallNew::PrintDataTo(StringStream* stream) { |
| 342 stream->Add("= "); | 333 stream->Add("= "); |
| 343 InputAt(0)->PrintTo(stream); | 334 InputAt(0)->PrintTo(stream); |
| 344 stream->Add(" #%d / ", arity()); | 335 stream->Add(" #%d / ", arity()); |
| 345 } | 336 } |
| 346 | 337 |
| 347 | 338 |
| 348 void LClassOfTest::PrintDataTo(StringStream* stream) { | |
| 349 stream->Add("= class_of_test("); | |
| 350 InputAt(0)->PrintTo(stream); | |
| 351 stream->Add(", \"%o\")", *hydrogen()->class_name()); | |
| 352 } | |
| 353 | |
| 354 | |
| 355 void LAccessArgumentsAt::PrintDataTo(StringStream* stream) { | 339 void LAccessArgumentsAt::PrintDataTo(StringStream* stream) { |
| 356 arguments()->PrintTo(stream); | 340 arguments()->PrintTo(stream); |
| 357 | 341 |
| 358 stream->Add(" length "); | 342 stream->Add(" length "); |
| 359 length()->PrintTo(stream); | 343 length()->PrintTo(stream); |
| 360 | 344 |
| 361 stream->Add(" index "); | 345 stream->Add(" index "); |
| 362 index()->PrintTo(stream); | 346 index()->PrintTo(stream); |
| 363 } | 347 } |
| 364 | 348 |
| (...skipping 21 matching lines...) Expand all Loading... |
| 386 for (int i = 0; i < graph()->blocks()->length(); ++i) { | 370 for (int i = 0; i < graph()->blocks()->length(); ++i) { |
| 387 HBasicBlock* block = graph()->blocks()->at(i); | 371 HBasicBlock* block = graph()->blocks()->at(i); |
| 388 int first = block->first_instruction_index(); | 372 int first = block->first_instruction_index(); |
| 389 int last = block->last_instruction_index(); | 373 int last = block->last_instruction_index(); |
| 390 LInstruction* first_instr = instructions()->at(first); | 374 LInstruction* first_instr = instructions()->at(first); |
| 391 LInstruction* last_instr = instructions()->at(last); | 375 LInstruction* last_instr = instructions()->at(last); |
| 392 | 376 |
| 393 LLabel* label = LLabel::cast(first_instr); | 377 LLabel* label = LLabel::cast(first_instr); |
| 394 if (last_instr->IsGoto()) { | 378 if (last_instr->IsGoto()) { |
| 395 LGoto* goto_instr = LGoto::cast(last_instr); | 379 LGoto* goto_instr = LGoto::cast(last_instr); |
| 396 if (!goto_instr->include_stack_check() && | 380 if (label->IsRedundant() && |
| 397 label->IsRedundant() && | |
| 398 !label->is_loop_header()) { | 381 !label->is_loop_header()) { |
| 399 bool can_eliminate = true; | 382 bool can_eliminate = true; |
| 400 for (int i = first + 1; i < last && can_eliminate; ++i) { | 383 for (int i = first + 1; i < last && can_eliminate; ++i) { |
| 401 LInstruction* cur = instructions()->at(i); | 384 LInstruction* cur = instructions()->at(i); |
| 402 if (cur->IsGap()) { | 385 if (cur->IsGap()) { |
| 403 LGap* gap = LGap::cast(cur); | 386 LGap* gap = LGap::cast(cur); |
| 404 if (!gap->IsRedundant()) { | 387 if (!gap->IsRedundant()) { |
| 405 can_eliminate = false; | 388 can_eliminate = false; |
| 406 } | 389 } |
| 407 } else { | 390 } else { |
| (...skipping 388 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 796 allocator_->RecordTemporary(operand); | 779 allocator_->RecordTemporary(operand); |
| 797 return operand; | 780 return operand; |
| 798 } | 781 } |
| 799 | 782 |
| 800 | 783 |
| 801 LInstruction* LChunkBuilder::DoBlockEntry(HBlockEntry* instr) { | 784 LInstruction* LChunkBuilder::DoBlockEntry(HBlockEntry* instr) { |
| 802 return new LLabel(instr->block()); | 785 return new LLabel(instr->block()); |
| 803 } | 786 } |
| 804 | 787 |
| 805 | 788 |
| 789 LInstruction* LChunkBuilder::DoSoftDeoptimize(HSoftDeoptimize* instr) { |
| 790 return AssignEnvironment(new LDeoptimize); |
| 791 } |
| 792 |
| 793 |
| 806 LInstruction* LChunkBuilder::DoDeoptimize(HDeoptimize* instr) { | 794 LInstruction* LChunkBuilder::DoDeoptimize(HDeoptimize* instr) { |
| 807 return AssignEnvironment(new LDeoptimize); | 795 return AssignEnvironment(new LDeoptimize); |
| 808 } | 796 } |
| 809 | 797 |
| 810 | 798 |
| 811 LInstruction* LChunkBuilder::DoBit(Token::Value op, | 799 LInstruction* LChunkBuilder::DoBit(Token::Value op, |
| 812 HBitwiseBinaryOperation* instr) { | 800 HBitwiseBinaryOperation* instr) { |
| 813 if (instr->representation().IsInteger32()) { | 801 if (instr->representation().IsInteger32()) { |
| 814 ASSERT(instr->left()->representation().IsInteger32()); | 802 ASSERT(instr->left()->representation().IsInteger32()); |
| 815 ASSERT(instr->right()->representation().IsInteger32()); | 803 ASSERT(instr->right()->representation().IsInteger32()); |
| (...skipping 20 matching lines...) Expand all Loading... |
| 836 ASSERT(instr->left()->representation().IsTagged()); | 824 ASSERT(instr->left()->representation().IsTagged()); |
| 837 ASSERT(instr->right()->representation().IsTagged()); | 825 ASSERT(instr->right()->representation().IsTagged()); |
| 838 | 826 |
| 839 LOperand* left = UseFixed(instr->left(), rdx); | 827 LOperand* left = UseFixed(instr->left(), rdx); |
| 840 LOperand* right = UseFixed(instr->right(), rax); | 828 LOperand* right = UseFixed(instr->right(), rax); |
| 841 LArithmeticT* result = new LArithmeticT(op, left, right); | 829 LArithmeticT* result = new LArithmeticT(op, left, right); |
| 842 return MarkAsCall(DefineFixed(result, rax), instr); | 830 return MarkAsCall(DefineFixed(result, rax), instr); |
| 843 } | 831 } |
| 844 | 832 |
| 845 ASSERT(instr->representation().IsInteger32()); | 833 ASSERT(instr->representation().IsInteger32()); |
| 846 ASSERT(instr->OperandAt(0)->representation().IsInteger32()); | 834 ASSERT(instr->left()->representation().IsInteger32()); |
| 847 ASSERT(instr->OperandAt(1)->representation().IsInteger32()); | 835 ASSERT(instr->right()->representation().IsInteger32()); |
| 848 LOperand* left = UseRegisterAtStart(instr->OperandAt(0)); | 836 LOperand* left = UseRegisterAtStart(instr->left()); |
| 849 | 837 |
| 850 HValue* right_value = instr->OperandAt(1); | 838 HValue* right_value = instr->right(); |
| 851 LOperand* right = NULL; | 839 LOperand* right = NULL; |
| 852 int constant_value = 0; | 840 int constant_value = 0; |
| 853 if (right_value->IsConstant()) { | 841 if (right_value->IsConstant()) { |
| 854 HConstant* constant = HConstant::cast(right_value); | 842 HConstant* constant = HConstant::cast(right_value); |
| 855 right = chunk_->DefineConstantOperand(constant); | 843 right = chunk_->DefineConstantOperand(constant); |
| 856 constant_value = constant->Integer32Value() & 0x1f; | 844 constant_value = constant->Integer32Value() & 0x1f; |
| 857 } else { | 845 } else { |
| 858 right = UseFixed(right_value, rcx); | 846 right = UseFixed(right_value, rcx); |
| 859 } | 847 } |
| 860 | 848 |
| (...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 977 if (current->has_position()) position_ = current->position(); | 965 if (current->has_position()) position_ = current->position(); |
| 978 LInstruction* instr = current->CompileToLithium(this); | 966 LInstruction* instr = current->CompileToLithium(this); |
| 979 | 967 |
| 980 if (instr != NULL) { | 968 if (instr != NULL) { |
| 981 if (FLAG_stress_pointer_maps && !instr->HasPointerMap()) { | 969 if (FLAG_stress_pointer_maps && !instr->HasPointerMap()) { |
| 982 instr = AssignPointerMap(instr); | 970 instr = AssignPointerMap(instr); |
| 983 } | 971 } |
| 984 if (FLAG_stress_environments && !instr->HasEnvironment()) { | 972 if (FLAG_stress_environments && !instr->HasEnvironment()) { |
| 985 instr = AssignEnvironment(instr); | 973 instr = AssignEnvironment(instr); |
| 986 } | 974 } |
| 987 if (current->IsTest() && !instr->IsGoto()) { | 975 instr->set_hydrogen_value(current); |
| 988 ASSERT(instr->IsControl()); | |
| 989 HTest* test = HTest::cast(current); | |
| 990 instr->set_hydrogen_value(test->value()); | |
| 991 HBasicBlock* first = test->FirstSuccessor(); | |
| 992 HBasicBlock* second = test->SecondSuccessor(); | |
| 993 ASSERT(first != NULL && second != NULL); | |
| 994 instr->SetBranchTargets(first->block_id(), second->block_id()); | |
| 995 } else { | |
| 996 instr->set_hydrogen_value(current); | |
| 997 } | |
| 998 | |
| 999 chunk_->AddInstruction(instr, current_block_); | 976 chunk_->AddInstruction(instr, current_block_); |
| 1000 } | 977 } |
| 1001 current_instruction_ = old_current; | 978 current_instruction_ = old_current; |
| 1002 } | 979 } |
| 1003 | 980 |
| 1004 | 981 |
| 1005 LEnvironment* LChunkBuilder::CreateEnvironment(HEnvironment* hydrogen_env) { | 982 LEnvironment* LChunkBuilder::CreateEnvironment(HEnvironment* hydrogen_env) { |
| 1006 if (hydrogen_env == NULL) return NULL; | 983 if (hydrogen_env == NULL) return NULL; |
| 1007 | 984 |
| 1008 LEnvironment* outer = CreateEnvironment(hydrogen_env->outer()); | 985 LEnvironment* outer = CreateEnvironment(hydrogen_env->outer()); |
| (...skipping 20 matching lines...) Expand all Loading... |
| 1029 op = UseAny(value); | 1006 op = UseAny(value); |
| 1030 } | 1007 } |
| 1031 result->AddValue(op, value->representation()); | 1008 result->AddValue(op, value->representation()); |
| 1032 } | 1009 } |
| 1033 | 1010 |
| 1034 return result; | 1011 return result; |
| 1035 } | 1012 } |
| 1036 | 1013 |
| 1037 | 1014 |
| 1038 LInstruction* LChunkBuilder::DoGoto(HGoto* instr) { | 1015 LInstruction* LChunkBuilder::DoGoto(HGoto* instr) { |
| 1039 LGoto* result = new LGoto(instr->FirstSuccessor()->block_id(), | 1016 return new LGoto(instr->FirstSuccessor()->block_id()); |
| 1040 instr->include_stack_check()); | |
| 1041 return (instr->include_stack_check()) | |
| 1042 ? AssignPointerMap(result) | |
| 1043 : result; | |
| 1044 } | 1017 } |
| 1045 | 1018 |
| 1046 | 1019 |
| 1047 LInstruction* LChunkBuilder::DoTest(HTest* instr) { | 1020 LInstruction* LChunkBuilder::DoBranch(HBranch* instr) { |
| 1048 HValue* v = instr->value(); | 1021 HValue* v = instr->value(); |
| 1049 if (!v->EmitAtUses()) { | 1022 if (v->EmitAtUses()) { |
| 1050 return new LBranch(UseRegisterAtStart(v)); | 1023 ASSERT(v->IsConstant()); |
| 1051 } else if (v->IsClassOfTest()) { | 1024 ASSERT(!v->representation().IsDouble()); |
| 1052 HClassOfTest* compare = HClassOfTest::cast(v); | |
| 1053 ASSERT(compare->value()->representation().IsTagged()); | |
| 1054 return new LClassOfTestAndBranch(UseTempRegister(compare->value()), | |
| 1055 TempRegister()); | |
| 1056 } else if (v->IsCompare()) { | |
| 1057 HCompare* compare = HCompare::cast(v); | |
| 1058 Token::Value op = compare->token(); | |
| 1059 HValue* left = compare->left(); | |
| 1060 HValue* right = compare->right(); | |
| 1061 Representation r = compare->GetInputRepresentation(); | |
| 1062 if (r.IsInteger32()) { | |
| 1063 ASSERT(left->representation().IsInteger32()); | |
| 1064 ASSERT(right->representation().IsInteger32()); | |
| 1065 return new LCmpIDAndBranch(UseRegisterAtStart(left), | |
| 1066 UseOrConstantAtStart(right)); | |
| 1067 } else if (r.IsDouble()) { | |
| 1068 ASSERT(left->representation().IsDouble()); | |
| 1069 ASSERT(right->representation().IsDouble()); | |
| 1070 return new LCmpIDAndBranch(UseRegisterAtStart(left), | |
| 1071 UseRegisterAtStart(right)); | |
| 1072 } else { | |
| 1073 ASSERT(left->representation().IsTagged()); | |
| 1074 ASSERT(right->representation().IsTagged()); | |
| 1075 bool reversed = op == Token::GT || op == Token::LTE; | |
| 1076 LOperand* left_operand = UseFixed(left, reversed ? rax : rdx); | |
| 1077 LOperand* right_operand = UseFixed(right, reversed ? rdx : rax); | |
| 1078 LCmpTAndBranch* result = new LCmpTAndBranch(left_operand, right_operand); | |
| 1079 return MarkAsCall(result, instr); | |
| 1080 } | |
| 1081 } else if (v->IsIsSmi()) { | |
| 1082 HIsSmi* compare = HIsSmi::cast(v); | |
| 1083 ASSERT(compare->value()->representation().IsTagged()); | |
| 1084 return new LIsSmiAndBranch(Use(compare->value())); | |
| 1085 } else if (v->IsIsUndetectable()) { | |
| 1086 HIsUndetectable* compare = HIsUndetectable::cast(v); | |
| 1087 ASSERT(compare->value()->representation().IsTagged()); | |
| 1088 return new LIsUndetectableAndBranch(UseRegisterAtStart(compare->value()), | |
| 1089 TempRegister()); | |
| 1090 } else if (v->IsHasInstanceType()) { | |
| 1091 HHasInstanceType* compare = HHasInstanceType::cast(v); | |
| 1092 ASSERT(compare->value()->representation().IsTagged()); | |
| 1093 return new LHasInstanceTypeAndBranch(UseRegisterAtStart(compare->value())); | |
| 1094 } else if (v->IsHasCachedArrayIndex()) { | |
| 1095 HHasCachedArrayIndex* compare = HHasCachedArrayIndex::cast(v); | |
| 1096 ASSERT(compare->value()->representation().IsTagged()); | |
| 1097 return new LHasCachedArrayIndexAndBranch( | |
| 1098 UseRegisterAtStart(compare->value())); | |
| 1099 } else if (v->IsIsNull()) { | |
| 1100 HIsNull* compare = HIsNull::cast(v); | |
| 1101 ASSERT(compare->value()->representation().IsTagged()); | |
| 1102 // We only need a temp register for non-strict compare. | |
| 1103 LOperand* temp = compare->is_strict() ? NULL : TempRegister(); | |
| 1104 return new LIsNullAndBranch(UseRegisterAtStart(compare->value()), temp); | |
| 1105 } else if (v->IsIsObject()) { | |
| 1106 HIsObject* compare = HIsObject::cast(v); | |
| 1107 ASSERT(compare->value()->representation().IsTagged()); | |
| 1108 return new LIsObjectAndBranch(UseRegisterAtStart(compare->value())); | |
| 1109 } else if (v->IsCompareJSObjectEq()) { | |
| 1110 HCompareJSObjectEq* compare = HCompareJSObjectEq::cast(v); | |
| 1111 return new LCmpJSObjectEqAndBranch(UseRegisterAtStart(compare->left()), | |
| 1112 UseRegisterAtStart(compare->right())); | |
| 1113 } else if (v->IsCompareSymbolEq()) { | |
| 1114 HCompareSymbolEq* compare = HCompareSymbolEq::cast(v); | |
| 1115 return new LCmpSymbolEqAndBranch(UseRegisterAtStart(compare->left()), | |
| 1116 UseRegisterAtStart(compare->right())); | |
| 1117 } else if (v->IsInstanceOf()) { | |
| 1118 HInstanceOf* instance_of = HInstanceOf::cast(v); | |
| 1119 LInstanceOfAndBranch* result = | |
| 1120 new LInstanceOfAndBranch(UseFixed(instance_of->left(), rax), | |
| 1121 UseFixed(instance_of->right(), rdx)); | |
| 1122 return MarkAsCall(result, instr); | |
| 1123 } else if (v->IsTypeofIs()) { | |
| 1124 HTypeofIs* typeof_is = HTypeofIs::cast(v); | |
| 1125 return new LTypeofIsAndBranch(UseTempRegister(typeof_is->value())); | |
| 1126 } else if (v->IsIsConstructCall()) { | |
| 1127 return new LIsConstructCallAndBranch(TempRegister()); | |
| 1128 } else if (v->IsConstant()) { | |
| 1129 HBasicBlock* successor = HConstant::cast(v)->ToBoolean() | 1025 HBasicBlock* successor = HConstant::cast(v)->ToBoolean() |
| 1130 ? instr->FirstSuccessor() | 1026 ? instr->FirstSuccessor() |
| 1131 : instr->SecondSuccessor(); | 1027 : instr->SecondSuccessor(); |
| 1132 return new LGoto(successor->block_id()); | 1028 return new LGoto(successor->block_id()); |
| 1133 } else { | |
| 1134 Abort("Undefined compare before branch"); | |
| 1135 return NULL; | |
| 1136 } | 1029 } |
| 1030 return new LBranch(UseRegisterAtStart(v)); |
| 1137 } | 1031 } |
| 1138 | 1032 |
| 1139 | 1033 |
| 1140 LInstruction* LChunkBuilder::DoCompareMap(HCompareMap* instr) { | 1034 LInstruction* LChunkBuilder::DoCompareMap(HCompareMap* instr) { |
| 1141 ASSERT(instr->value()->representation().IsTagged()); | 1035 ASSERT(instr->value()->representation().IsTagged()); |
| 1142 LOperand* value = UseRegisterAtStart(instr->value()); | 1036 LOperand* value = UseRegisterAtStart(instr->value()); |
| 1143 return new LCmpMapAndBranch(value); | 1037 return new LCmpMapAndBranch(value); |
| 1144 } | 1038 } |
| 1145 | 1039 |
| 1146 | 1040 |
| (...skipping 11 matching lines...) Expand all Loading... |
| 1158 LOperand* left = UseFixed(instr->left(), rax); | 1052 LOperand* left = UseFixed(instr->left(), rax); |
| 1159 LOperand* right = UseFixed(instr->right(), rdx); | 1053 LOperand* right = UseFixed(instr->right(), rdx); |
| 1160 LInstanceOf* result = new LInstanceOf(left, right); | 1054 LInstanceOf* result = new LInstanceOf(left, right); |
| 1161 return MarkAsCall(DefineFixed(result, rax), instr); | 1055 return MarkAsCall(DefineFixed(result, rax), instr); |
| 1162 } | 1056 } |
| 1163 | 1057 |
| 1164 | 1058 |
| 1165 LInstruction* LChunkBuilder::DoInstanceOfKnownGlobal( | 1059 LInstruction* LChunkBuilder::DoInstanceOfKnownGlobal( |
| 1166 HInstanceOfKnownGlobal* instr) { | 1060 HInstanceOfKnownGlobal* instr) { |
| 1167 LInstanceOfKnownGlobal* result = | 1061 LInstanceOfKnownGlobal* result = |
| 1168 new LInstanceOfKnownGlobal(UseFixed(instr->value(), rax), | 1062 new LInstanceOfKnownGlobal(UseFixed(instr->left(), rax), |
| 1169 FixedTemp(rdi)); | 1063 FixedTemp(rdi)); |
| 1170 return MarkAsCall(DefineFixed(result, rax), instr); | 1064 return MarkAsCall(DefineFixed(result, rax), instr); |
| 1171 } | 1065 } |
| 1172 | 1066 |
| 1173 | 1067 |
| 1174 LInstruction* LChunkBuilder::DoApplyArguments(HApplyArguments* instr) { | 1068 LInstruction* LChunkBuilder::DoApplyArguments(HApplyArguments* instr) { |
| 1175 LOperand* function = UseFixed(instr->function(), rdi); | 1069 LOperand* function = UseFixed(instr->function(), rdi); |
| 1176 LOperand* receiver = UseFixed(instr->receiver(), rax); | 1070 LOperand* receiver = UseFixed(instr->receiver(), rax); |
| 1177 LOperand* length = UseFixed(instr->length(), rbx); | 1071 LOperand* length = UseFixed(instr->length(), rbx); |
| 1178 LOperand* elements = UseFixed(instr->elements(), rcx); | 1072 LOperand* elements = UseFixed(instr->elements(), rcx); |
| 1179 LApplyArguments* result = new LApplyArguments(function, | 1073 LApplyArguments* result = new LApplyArguments(function, |
| 1180 receiver, | 1074 receiver, |
| 1181 length, | 1075 length, |
| 1182 elements); | 1076 elements); |
| 1183 return MarkAsCall(DefineFixed(result, rax), instr, CAN_DEOPTIMIZE_EAGERLY); | 1077 return MarkAsCall(DefineFixed(result, rax), instr, CAN_DEOPTIMIZE_EAGERLY); |
| 1184 } | 1078 } |
| 1185 | 1079 |
| 1186 | 1080 |
| 1187 LInstruction* LChunkBuilder::DoPushArgument(HPushArgument* instr) { | 1081 LInstruction* LChunkBuilder::DoPushArgument(HPushArgument* instr) { |
| 1188 ++argument_count_; | 1082 ++argument_count_; |
| 1189 LOperand* argument = UseOrConstant(instr->argument()); | 1083 LOperand* argument = UseOrConstant(instr->argument()); |
| 1190 return new LPushArgument(argument); | 1084 return new LPushArgument(argument); |
| 1191 } | 1085 } |
| 1192 | 1086 |
| 1193 | 1087 |
| 1088 LInstruction* LChunkBuilder::DoThisFunction(HThisFunction* instr) { |
| 1089 return instr->HasNoUses() ? NULL : DefineAsRegister(new LThisFunction); |
| 1090 } |
| 1091 |
| 1092 |
| 1194 LInstruction* LChunkBuilder::DoContext(HContext* instr) { | 1093 LInstruction* LChunkBuilder::DoContext(HContext* instr) { |
| 1195 return instr->HasNoUses() ? NULL : DefineAsRegister(new LContext); | 1094 return instr->HasNoUses() ? NULL : DefineAsRegister(new LContext); |
| 1196 } | 1095 } |
| 1197 | 1096 |
| 1198 | 1097 |
| 1199 LInstruction* LChunkBuilder::DoOuterContext(HOuterContext* instr) { | 1098 LInstruction* LChunkBuilder::DoOuterContext(HOuterContext* instr) { |
| 1200 LOperand* context = UseRegisterAtStart(instr->value()); | 1099 LOperand* context = UseRegisterAtStart(instr->value()); |
| 1201 return DefineAsRegister(new LOuterContext(context)); | 1100 return DefineAsRegister(new LOuterContext(context)); |
| 1202 } | 1101 } |
| 1203 | 1102 |
| (...skipping 270 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1474 UseFixed(instr->right(), rdx); | 1373 UseFixed(instr->right(), rdx); |
| 1475 #else | 1374 #else |
| 1476 UseFixed(instr->right(), rdi); | 1375 UseFixed(instr->right(), rdi); |
| 1477 #endif | 1376 #endif |
| 1478 LPower* result = new LPower(left, right); | 1377 LPower* result = new LPower(left, right); |
| 1479 return MarkAsCall(DefineFixedDouble(result, xmm1), instr, | 1378 return MarkAsCall(DefineFixedDouble(result, xmm1), instr, |
| 1480 CAN_DEOPTIMIZE_EAGERLY); | 1379 CAN_DEOPTIMIZE_EAGERLY); |
| 1481 } | 1380 } |
| 1482 | 1381 |
| 1483 | 1382 |
| 1484 LInstruction* LChunkBuilder::DoCompare(HCompare* instr) { | 1383 LInstruction* LChunkBuilder::DoCompareGeneric(HCompareGeneric* instr) { |
| 1485 Token::Value op = instr->token(); | 1384 Token::Value op = instr->token(); |
| 1385 ASSERT(instr->left()->representation().IsTagged()); |
| 1386 ASSERT(instr->right()->representation().IsTagged()); |
| 1387 bool reversed = (op == Token::GT || op == Token::LTE); |
| 1388 LOperand* left = UseFixed(instr->left(), reversed ? rax : rdx); |
| 1389 LOperand* right = UseFixed(instr->right(), reversed ? rdx : rax); |
| 1390 LCmpT* result = new LCmpT(left, right); |
| 1391 return MarkAsCall(DefineFixed(result, rax), instr); |
| 1392 } |
| 1393 |
| 1394 |
| 1395 LInstruction* LChunkBuilder::DoCompareIDAndBranch( |
| 1396 HCompareIDAndBranch* instr) { |
| 1486 Representation r = instr->GetInputRepresentation(); | 1397 Representation r = instr->GetInputRepresentation(); |
| 1487 if (r.IsInteger32()) { | 1398 if (r.IsInteger32()) { |
| 1488 ASSERT(instr->left()->representation().IsInteger32()); | 1399 ASSERT(instr->left()->representation().IsInteger32()); |
| 1489 ASSERT(instr->right()->representation().IsInteger32()); | 1400 ASSERT(instr->right()->representation().IsInteger32()); |
| 1490 LOperand* left = UseRegisterAtStart(instr->left()); | 1401 LOperand* left = UseRegisterAtStart(instr->left()); |
| 1491 LOperand* right = UseOrConstantAtStart(instr->right()); | 1402 LOperand* right = UseOrConstantAtStart(instr->right()); |
| 1492 return DefineAsRegister(new LCmpID(left, right)); | 1403 return new LCmpIDAndBranch(left, right); |
| 1493 } else if (r.IsDouble()) { | 1404 } else { |
| 1405 ASSERT(r.IsDouble()); |
| 1494 ASSERT(instr->left()->representation().IsDouble()); | 1406 ASSERT(instr->left()->representation().IsDouble()); |
| 1495 ASSERT(instr->right()->representation().IsDouble()); | 1407 ASSERT(instr->right()->representation().IsDouble()); |
| 1496 LOperand* left = UseRegisterAtStart(instr->left()); | 1408 LOperand* left = UseRegisterAtStart(instr->left()); |
| 1497 LOperand* right = UseRegisterAtStart(instr->right()); | 1409 LOperand* right = UseRegisterAtStart(instr->right()); |
| 1498 return DefineAsRegister(new LCmpID(left, right)); | 1410 return new LCmpIDAndBranch(left, right); |
| 1499 } else { | |
| 1500 ASSERT(instr->left()->representation().IsTagged()); | |
| 1501 ASSERT(instr->right()->representation().IsTagged()); | |
| 1502 bool reversed = (op == Token::GT || op == Token::LTE); | |
| 1503 LOperand* left = UseFixed(instr->left(), reversed ? rax : rdx); | |
| 1504 LOperand* right = UseFixed(instr->right(), reversed ? rdx : rax); | |
| 1505 LCmpT* result = new LCmpT(left, right); | |
| 1506 return MarkAsCall(DefineFixed(result, rax), instr); | |
| 1507 } | 1411 } |
| 1508 } | 1412 } |
| 1509 | 1413 |
| 1510 | 1414 |
| 1511 LInstruction* LChunkBuilder::DoCompareJSObjectEq( | 1415 LInstruction* LChunkBuilder::DoCompareObjectEqAndBranch( |
| 1512 HCompareJSObjectEq* instr) { | 1416 HCompareObjectEqAndBranch* instr) { |
| 1513 LOperand* left = UseRegisterAtStart(instr->left()); | 1417 LOperand* left = UseRegisterAtStart(instr->left()); |
| 1514 LOperand* right = UseRegisterAtStart(instr->right()); | 1418 LOperand* right = UseRegisterAtStart(instr->right()); |
| 1515 LCmpJSObjectEq* result = new LCmpJSObjectEq(left, right); | 1419 return new LCmpObjectEqAndBranch(left, right); |
| 1516 return DefineAsRegister(result); | |
| 1517 } | 1420 } |
| 1518 | 1421 |
| 1519 | 1422 |
| 1520 LInstruction* LChunkBuilder::DoCompareSymbolEq( | 1423 LInstruction* LChunkBuilder::DoCompareConstantEqAndBranch( |
| 1521 HCompareSymbolEq* instr) { | 1424 HCompareConstantEqAndBranch* instr) { |
| 1522 LOperand* left = UseRegisterAtStart(instr->left()); | 1425 return new LCmpConstantEqAndBranch(UseRegisterAtStart(instr->value())); |
| 1523 LOperand* right = UseRegisterAtStart(instr->right()); | |
| 1524 LCmpSymbolEq* result = new LCmpSymbolEq(left, right); | |
| 1525 return DefineAsRegister(result); | |
| 1526 } | 1426 } |
| 1527 | 1427 |
| 1528 | 1428 |
| 1529 LInstruction* LChunkBuilder::DoIsNull(HIsNull* instr) { | 1429 LInstruction* LChunkBuilder::DoIsNullAndBranch(HIsNullAndBranch* instr) { |
| 1530 ASSERT(instr->value()->representation().IsTagged()); | 1430 ASSERT(instr->value()->representation().IsTagged()); |
| 1531 LOperand* value = UseRegisterAtStart(instr->value()); | 1431 LOperand* temp = instr->is_strict() ? NULL : TempRegister(); |
| 1532 | 1432 return new LIsNullAndBranch(UseRegisterAtStart(instr->value()), temp); |
| 1533 return DefineAsRegister(new LIsNull(value)); | |
| 1534 } | 1433 } |
| 1535 | 1434 |
| 1536 | 1435 |
| 1537 LInstruction* LChunkBuilder::DoIsObject(HIsObject* instr) { | 1436 LInstruction* LChunkBuilder::DoIsObjectAndBranch(HIsObjectAndBranch* instr) { |
| 1538 ASSERT(instr->value()->representation().IsTagged()); | 1437 ASSERT(instr->value()->representation().IsTagged()); |
| 1539 LOperand* value = UseRegister(instr->value()); | 1438 return new LIsObjectAndBranch(UseRegisterAtStart(instr->value())); |
| 1540 | |
| 1541 return DefineAsRegister(new LIsObject(value)); | |
| 1542 } | 1439 } |
| 1543 | 1440 |
| 1544 | 1441 |
| 1545 LInstruction* LChunkBuilder::DoIsSmi(HIsSmi* instr) { | 1442 LInstruction* LChunkBuilder::DoIsSmiAndBranch(HIsSmiAndBranch* instr) { |
| 1546 ASSERT(instr->value()->representation().IsTagged()); | 1443 ASSERT(instr->value()->representation().IsTagged()); |
| 1547 LOperand* value = UseAtStart(instr->value()); | 1444 return new LIsSmiAndBranch(Use(instr->value())); |
| 1548 | |
| 1549 return DefineAsRegister(new LIsSmi(value)); | |
| 1550 } | 1445 } |
| 1551 | 1446 |
| 1552 | 1447 |
| 1553 LInstruction* LChunkBuilder::DoIsUndetectable(HIsUndetectable* instr) { | 1448 LInstruction* LChunkBuilder::DoIsUndetectableAndBranch( |
| 1449 HIsUndetectableAndBranch* instr) { |
| 1554 ASSERT(instr->value()->representation().IsTagged()); | 1450 ASSERT(instr->value()->representation().IsTagged()); |
| 1555 LOperand* value = UseRegisterAtStart(instr->value()); | 1451 return new LIsUndetectableAndBranch(UseRegisterAtStart(instr->value()), |
| 1556 | 1452 TempRegister()); |
| 1557 return DefineAsRegister(new LIsUndetectable(value)); | |
| 1558 } | 1453 } |
| 1559 | 1454 |
| 1560 | 1455 |
| 1561 LInstruction* LChunkBuilder::DoHasInstanceType(HHasInstanceType* instr) { | 1456 LInstruction* LChunkBuilder::DoHasInstanceTypeAndBranch( |
| 1457 HHasInstanceTypeAndBranch* instr) { |
| 1562 ASSERT(instr->value()->representation().IsTagged()); | 1458 ASSERT(instr->value()->representation().IsTagged()); |
| 1563 LOperand* value = UseRegisterAtStart(instr->value()); | 1459 return new LHasInstanceTypeAndBranch(UseRegisterAtStart(instr->value())); |
| 1564 | |
| 1565 return DefineAsRegister(new LHasInstanceType(value)); | |
| 1566 } | 1460 } |
| 1567 | 1461 |
| 1568 | 1462 |
| 1569 LInstruction* LChunkBuilder::DoGetCachedArrayIndex( | 1463 LInstruction* LChunkBuilder::DoGetCachedArrayIndex( |
| 1570 HGetCachedArrayIndex* instr) { | 1464 HGetCachedArrayIndex* instr) { |
| 1571 ASSERT(instr->value()->representation().IsTagged()); | 1465 ASSERT(instr->value()->representation().IsTagged()); |
| 1572 LOperand* value = UseRegisterAtStart(instr->value()); | 1466 LOperand* value = UseRegisterAtStart(instr->value()); |
| 1573 | 1467 |
| 1574 return DefineAsRegister(new LGetCachedArrayIndex(value)); | 1468 return DefineAsRegister(new LGetCachedArrayIndex(value)); |
| 1575 } | 1469 } |
| 1576 | 1470 |
| 1577 | 1471 |
| 1578 LInstruction* LChunkBuilder::DoHasCachedArrayIndex( | 1472 LInstruction* LChunkBuilder::DoHasCachedArrayIndexAndBranch( |
| 1579 HHasCachedArrayIndex* instr) { | 1473 HHasCachedArrayIndexAndBranch* instr) { |
| 1580 ASSERT(instr->value()->representation().IsTagged()); | 1474 ASSERT(instr->value()->representation().IsTagged()); |
| 1581 LOperand* value = UseRegister(instr->value()); | 1475 return new LHasCachedArrayIndexAndBranch(UseRegisterAtStart(instr->value())); |
| 1582 return DefineAsRegister(new LHasCachedArrayIndex(value)); | |
| 1583 } | 1476 } |
| 1584 | 1477 |
| 1585 | 1478 |
| 1586 LInstruction* LChunkBuilder::DoClassOfTest(HClassOfTest* instr) { | 1479 LInstruction* LChunkBuilder::DoClassOfTestAndBranch( |
| 1587 Abort("Unimplemented: %s", "DoClassOfTest"); | 1480 HClassOfTestAndBranch* instr) { |
| 1588 return NULL; | 1481 return new LClassOfTestAndBranch(UseTempRegister(instr->value()), |
| 1482 TempRegister()); |
| 1589 } | 1483 } |
| 1590 | 1484 |
| 1591 | 1485 |
| 1592 LInstruction* LChunkBuilder::DoJSArrayLength(HJSArrayLength* instr) { | 1486 LInstruction* LChunkBuilder::DoJSArrayLength(HJSArrayLength* instr) { |
| 1593 LOperand* array = UseRegisterAtStart(instr->value()); | 1487 LOperand* array = UseRegisterAtStart(instr->value()); |
| 1594 return DefineAsRegister(new LJSArrayLength(array)); | 1488 return DefineAsRegister(new LJSArrayLength(array)); |
| 1595 } | 1489 } |
| 1596 | 1490 |
| 1597 | 1491 |
| 1598 LInstruction* LChunkBuilder::DoFixedArrayLength(HFixedArrayLength* instr) { | 1492 LInstruction* LChunkBuilder::DoFixedArrayLength(HFixedArrayLength* instr) { |
| 1599 LOperand* array = UseRegisterAtStart(instr->value()); | 1493 LOperand* array = UseRegisterAtStart(instr->value()); |
| 1600 return DefineAsRegister(new LFixedArrayLength(array)); | 1494 return DefineAsRegister(new LFixedArrayLength(array)); |
| 1601 } | 1495 } |
| 1602 | 1496 |
| 1603 | 1497 |
| 1604 LInstruction* LChunkBuilder::DoExternalArrayLength( | 1498 LInstruction* LChunkBuilder::DoExternalArrayLength( |
| 1605 HExternalArrayLength* instr) { | 1499 HExternalArrayLength* instr) { |
| 1606 LOperand* array = UseRegisterAtStart(instr->value()); | 1500 LOperand* array = UseRegisterAtStart(instr->value()); |
| 1607 return DefineAsRegister(new LExternalArrayLength(array)); | 1501 return DefineAsRegister(new LExternalArrayLength(array)); |
| 1608 } | 1502 } |
| 1609 | 1503 |
| 1610 | 1504 |
| 1505 LInstruction* LChunkBuilder::DoElementsKind(HElementsKind* instr) { |
| 1506 LOperand* object = UseRegisterAtStart(instr->value()); |
| 1507 return DefineAsRegister(new LElementsKind(object)); |
| 1508 } |
| 1509 |
| 1510 |
| 1611 LInstruction* LChunkBuilder::DoValueOf(HValueOf* instr) { | 1511 LInstruction* LChunkBuilder::DoValueOf(HValueOf* instr) { |
| 1612 LOperand* object = UseRegister(instr->value()); | 1512 LOperand* object = UseRegister(instr->value()); |
| 1613 LValueOf* result = new LValueOf(object); | 1513 LValueOf* result = new LValueOf(object); |
| 1614 return AssignEnvironment(DefineSameAsFirst(result)); | 1514 return AssignEnvironment(DefineSameAsFirst(result)); |
| 1615 } | 1515 } |
| 1616 | 1516 |
| 1617 | 1517 |
| 1618 LInstruction* LChunkBuilder::DoBoundsCheck(HBoundsCheck* instr) { | 1518 LInstruction* LChunkBuilder::DoBoundsCheck(HBoundsCheck* instr) { |
| 1619 return AssignEnvironment(new LBoundsCheck(UseRegisterAtStart(instr->index()), | 1519 return AssignEnvironment(new LBoundsCheck(UseRegisterAtStart(instr->index()), |
| 1620 Use(instr->length()))); | 1520 Use(instr->length()))); |
| 1621 } | 1521 } |
| 1622 | 1522 |
| 1623 | 1523 |
| 1624 LInstruction* LChunkBuilder::DoAbnormalExit(HAbnormalExit* instr) { | 1524 LInstruction* LChunkBuilder::DoAbnormalExit(HAbnormalExit* instr) { |
| 1625 // The control instruction marking the end of a block that completed | 1525 // The control instruction marking the end of a block that completed |
| 1626 // abruptly (e.g., threw an exception). There is nothing specific to do. | 1526 // abruptly (e.g., threw an exception). There is nothing specific to do. |
| 1627 return NULL; | 1527 return NULL; |
| 1628 } | 1528 } |
| 1629 | 1529 |
| 1630 | 1530 |
| 1631 LInstruction* LChunkBuilder::DoThrow(HThrow* instr) { | 1531 LInstruction* LChunkBuilder::DoThrow(HThrow* instr) { |
| 1632 LOperand* value = UseFixed(instr->value(), rax); | 1532 LOperand* value = UseFixed(instr->value(), rax); |
| 1633 return MarkAsCall(new LThrow(value), instr); | 1533 return MarkAsCall(new LThrow(value), instr); |
| 1634 } | 1534 } |
| 1635 | 1535 |
| 1636 | 1536 |
| 1537 LInstruction* LChunkBuilder::DoUseConst(HUseConst* instr) { |
| 1538 return NULL; |
| 1539 } |
| 1540 |
| 1541 |
| 1637 LInstruction* LChunkBuilder::DoForceRepresentation(HForceRepresentation* bad) { | 1542 LInstruction* LChunkBuilder::DoForceRepresentation(HForceRepresentation* bad) { |
| 1638 // All HForceRepresentation instructions should be eliminated in the | 1543 // All HForceRepresentation instructions should be eliminated in the |
| 1639 // representation change phase of Hydrogen. | 1544 // representation change phase of Hydrogen. |
| 1640 UNREACHABLE(); | 1545 UNREACHABLE(); |
| 1641 return NULL; | 1546 return NULL; |
| 1642 } | 1547 } |
| 1643 | 1548 |
| 1644 | 1549 |
| 1645 LInstruction* LChunkBuilder::DoChange(HChange* instr) { | 1550 LInstruction* LChunkBuilder::DoChange(HChange* instr) { |
| 1646 Representation from = instr->from(); | 1551 Representation from = instr->from(); |
| 1647 Representation to = instr->to(); | 1552 Representation to = instr->to(); |
| 1648 if (from.IsTagged()) { | 1553 if (from.IsTagged()) { |
| 1649 if (to.IsDouble()) { | 1554 if (to.IsDouble()) { |
| 1650 LOperand* value = UseRegister(instr->value()); | 1555 LOperand* value = UseRegister(instr->value()); |
| 1651 LNumberUntagD* res = new LNumberUntagD(value); | 1556 LNumberUntagD* res = new LNumberUntagD(value); |
| 1652 return AssignEnvironment(DefineAsRegister(res)); | 1557 return AssignEnvironment(DefineAsRegister(res)); |
| 1653 } else { | 1558 } else { |
| 1654 ASSERT(to.IsInteger32()); | 1559 ASSERT(to.IsInteger32()); |
| 1655 LOperand* value = UseRegister(instr->value()); | 1560 LOperand* value = UseRegister(instr->value()); |
| 1656 bool needs_check = !instr->value()->type().IsSmi(); | 1561 bool needs_check = !instr->value()->type().IsSmi(); |
| 1657 if (needs_check) { | 1562 if (needs_check) { |
| 1658 LOperand* xmm_temp = instr->CanTruncateToInt32() ? NULL | 1563 bool truncating = instr->CanTruncateToInt32(); |
| 1659 : FixedTemp(xmm1); | 1564 LOperand* xmm_temp = truncating ? NULL : FixedTemp(xmm1); |
| 1660 LTaggedToI* res = new LTaggedToI(value, xmm_temp); | 1565 LTaggedToI* res = new LTaggedToI(value, xmm_temp); |
| 1661 return AssignEnvironment(DefineSameAsFirst(res)); | 1566 return AssignEnvironment(DefineSameAsFirst(res)); |
| 1662 } else { | 1567 } else { |
| 1663 return DefineSameAsFirst(new LSmiUntag(value, needs_check)); | 1568 return DefineSameAsFirst(new LSmiUntag(value, needs_check)); |
| 1664 } | 1569 } |
| 1665 } | 1570 } |
| 1666 } else if (from.IsDouble()) { | 1571 } else if (from.IsDouble()) { |
| 1667 if (to.IsTagged()) { | 1572 if (to.IsTagged()) { |
| 1668 LOperand* value = UseRegister(instr->value()); | 1573 LOperand* value = UseRegister(instr->value()); |
| 1669 LOperand* temp = TempRegister(); | 1574 LOperand* temp = TempRegister(); |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1750 // Register allocator doesn't (yet) support allocation of double | 1655 // Register allocator doesn't (yet) support allocation of double |
| 1751 // temps. Reserve xmm1 explicitly. | 1656 // temps. Reserve xmm1 explicitly. |
| 1752 LClampTToUint8* result = new LClampTToUint8(reg, | 1657 LClampTToUint8* result = new LClampTToUint8(reg, |
| 1753 TempRegister(), | 1658 TempRegister(), |
| 1754 FixedTemp(xmm1)); | 1659 FixedTemp(xmm1)); |
| 1755 return AssignEnvironment(DefineSameAsFirst(result)); | 1660 return AssignEnvironment(DefineSameAsFirst(result)); |
| 1756 } | 1661 } |
| 1757 } | 1662 } |
| 1758 | 1663 |
| 1759 | 1664 |
| 1665 LInstruction* LChunkBuilder::DoToInt32(HToInt32* instr) { |
| 1666 HValue* value = instr->value(); |
| 1667 Representation input_rep = value->representation(); |
| 1668 LOperand* reg = UseRegister(value); |
| 1669 if (input_rep.IsDouble()) { |
| 1670 return AssignEnvironment(DefineAsRegister(new LDoubleToI(reg))); |
| 1671 } else if (input_rep.IsInteger32()) { |
| 1672 // Canonicalization should already have removed the hydrogen instruction in |
| 1673 // this case, since it is a noop. |
| 1674 UNREACHABLE(); |
| 1675 return NULL; |
| 1676 } else { |
| 1677 ASSERT(input_rep.IsTagged()); |
| 1678 LOperand* reg = UseRegister(value); |
| 1679 // Register allocator doesn't (yet) support allocation of double |
| 1680 // temps. Reserve xmm1 explicitly. |
| 1681 LOperand* xmm_temp = |
| 1682 CpuFeatures::IsSupported(SSE3) |
| 1683 ? NULL |
| 1684 : FixedTemp(xmm1); |
| 1685 return AssignEnvironment( |
| 1686 DefineSameAsFirst(new LTaggedToI(reg, xmm_temp))); |
| 1687 } |
| 1688 } |
| 1689 |
| 1690 |
| 1760 LInstruction* LChunkBuilder::DoReturn(HReturn* instr) { | 1691 LInstruction* LChunkBuilder::DoReturn(HReturn* instr) { |
| 1761 return new LReturn(UseFixed(instr->value(), rax)); | 1692 return new LReturn(UseFixed(instr->value(), rax)); |
| 1762 } | 1693 } |
| 1763 | 1694 |
| 1764 | 1695 |
| 1765 LInstruction* LChunkBuilder::DoConstant(HConstant* instr) { | 1696 LInstruction* LChunkBuilder::DoConstant(HConstant* instr) { |
| 1766 Representation r = instr->representation(); | 1697 Representation r = instr->representation(); |
| 1767 if (r.IsInteger32()) { | 1698 if (r.IsInteger32()) { |
| 1768 return DefineAsRegister(new LConstantI); | 1699 return DefineAsRegister(new LConstantI); |
| 1769 } else if (r.IsDouble()) { | 1700 } else if (r.IsDouble()) { |
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1888 ASSERT(instr->key()->representation().IsInteger32()); | 1819 ASSERT(instr->key()->representation().IsInteger32()); |
| 1889 LOperand* obj = UseRegisterAtStart(instr->object()); | 1820 LOperand* obj = UseRegisterAtStart(instr->object()); |
| 1890 LOperand* key = UseRegisterAtStart(instr->key()); | 1821 LOperand* key = UseRegisterAtStart(instr->key()); |
| 1891 LLoadKeyedFastElement* result = new LLoadKeyedFastElement(obj, key); | 1822 LLoadKeyedFastElement* result = new LLoadKeyedFastElement(obj, key); |
| 1892 return AssignEnvironment(DefineSameAsFirst(result)); | 1823 return AssignEnvironment(DefineSameAsFirst(result)); |
| 1893 } | 1824 } |
| 1894 | 1825 |
| 1895 | 1826 |
| 1896 LInstruction* LChunkBuilder::DoLoadKeyedSpecializedArrayElement( | 1827 LInstruction* LChunkBuilder::DoLoadKeyedSpecializedArrayElement( |
| 1897 HLoadKeyedSpecializedArrayElement* instr) { | 1828 HLoadKeyedSpecializedArrayElement* instr) { |
| 1898 ExternalArrayType array_type = instr->array_type(); | 1829 JSObject::ElementsKind elements_kind = instr->elements_kind(); |
| 1899 Representation representation(instr->representation()); | 1830 Representation representation(instr->representation()); |
| 1900 ASSERT( | 1831 ASSERT( |
| 1901 (representation.IsInteger32() && (array_type != kExternalFloatArray && | 1832 (representation.IsInteger32() && |
| 1902 array_type != kExternalDoubleArray)) || | 1833 (elements_kind != JSObject::EXTERNAL_FLOAT_ELEMENTS) && |
| 1903 (representation.IsDouble() && (array_type == kExternalFloatArray || | 1834 (elements_kind != JSObject::EXTERNAL_DOUBLE_ELEMENTS)) || |
| 1904 array_type == kExternalDoubleArray))); | 1835 (representation.IsDouble() && |
| 1836 ((elements_kind == JSObject::EXTERNAL_FLOAT_ELEMENTS) || |
| 1837 (elements_kind == JSObject::EXTERNAL_DOUBLE_ELEMENTS)))); |
| 1905 ASSERT(instr->key()->representation().IsInteger32()); | 1838 ASSERT(instr->key()->representation().IsInteger32()); |
| 1906 LOperand* external_pointer = UseRegister(instr->external_pointer()); | 1839 LOperand* external_pointer = UseRegister(instr->external_pointer()); |
| 1907 LOperand* key = UseRegisterOrConstant(instr->key()); | 1840 LOperand* key = UseRegisterOrConstant(instr->key()); |
| 1908 LLoadKeyedSpecializedArrayElement* result = | 1841 LLoadKeyedSpecializedArrayElement* result = |
| 1909 new LLoadKeyedSpecializedArrayElement(external_pointer, key); | 1842 new LLoadKeyedSpecializedArrayElement(external_pointer, key); |
| 1910 LInstruction* load_instr = DefineAsRegister(result); | 1843 LInstruction* load_instr = DefineAsRegister(result); |
| 1911 // An unsigned int array load might overflow and cause a deopt, make sure it | 1844 // An unsigned int array load might overflow and cause a deopt, make sure it |
| 1912 // has an environment. | 1845 // has an environment. |
| 1913 return (array_type == kExternalUnsignedIntArray) ? | 1846 return (elements_kind == JSObject::EXTERNAL_UNSIGNED_INT_ELEMENTS) ? |
| 1914 AssignEnvironment(load_instr) : load_instr; | 1847 AssignEnvironment(load_instr) : load_instr; |
| 1915 } | 1848 } |
| 1916 | 1849 |
| 1917 | 1850 |
| 1918 LInstruction* LChunkBuilder::DoLoadKeyedGeneric(HLoadKeyedGeneric* instr) { | 1851 LInstruction* LChunkBuilder::DoLoadKeyedGeneric(HLoadKeyedGeneric* instr) { |
| 1919 LOperand* object = UseFixed(instr->object(), rdx); | 1852 LOperand* object = UseFixed(instr->object(), rdx); |
| 1920 LOperand* key = UseFixed(instr->key(), rax); | 1853 LOperand* key = UseFixed(instr->key(), rax); |
| 1921 | 1854 |
| 1922 LLoadKeyedGeneric* result = new LLoadKeyedGeneric(object, key); | 1855 LLoadKeyedGeneric* result = new LLoadKeyedGeneric(object, key); |
| 1923 return MarkAsCall(DefineFixed(result, rax), instr); | 1856 return MarkAsCall(DefineFixed(result, rax), instr); |
| (...skipping 15 matching lines...) Expand all Loading... |
| 1939 ? UseTempRegister(instr->key()) | 1872 ? UseTempRegister(instr->key()) |
| 1940 : UseRegisterOrConstantAtStart(instr->key()); | 1873 : UseRegisterOrConstantAtStart(instr->key()); |
| 1941 | 1874 |
| 1942 return AssignEnvironment(new LStoreKeyedFastElement(obj, key, val)); | 1875 return AssignEnvironment(new LStoreKeyedFastElement(obj, key, val)); |
| 1943 } | 1876 } |
| 1944 | 1877 |
| 1945 | 1878 |
| 1946 LInstruction* LChunkBuilder::DoStoreKeyedSpecializedArrayElement( | 1879 LInstruction* LChunkBuilder::DoStoreKeyedSpecializedArrayElement( |
| 1947 HStoreKeyedSpecializedArrayElement* instr) { | 1880 HStoreKeyedSpecializedArrayElement* instr) { |
| 1948 Representation representation(instr->value()->representation()); | 1881 Representation representation(instr->value()->representation()); |
| 1949 ExternalArrayType array_type = instr->array_type(); | 1882 JSObject::ElementsKind elements_kind = instr->elements_kind(); |
| 1950 ASSERT( | 1883 ASSERT( |
| 1951 (representation.IsInteger32() && (array_type != kExternalFloatArray && | 1884 (representation.IsInteger32() && |
| 1952 array_type != kExternalDoubleArray)) || | 1885 (elements_kind != JSObject::EXTERNAL_FLOAT_ELEMENTS) && |
| 1953 (representation.IsDouble() && (array_type == kExternalFloatArray || | 1886 (elements_kind != JSObject::EXTERNAL_DOUBLE_ELEMENTS)) || |
| 1954 array_type == kExternalDoubleArray))); | 1887 (representation.IsDouble() && |
| 1888 ((elements_kind == JSObject::EXTERNAL_FLOAT_ELEMENTS) || |
| 1889 (elements_kind == JSObject::EXTERNAL_DOUBLE_ELEMENTS)))); |
| 1955 ASSERT(instr->external_pointer()->representation().IsExternal()); | 1890 ASSERT(instr->external_pointer()->representation().IsExternal()); |
| 1956 ASSERT(instr->key()->representation().IsInteger32()); | 1891 ASSERT(instr->key()->representation().IsInteger32()); |
| 1957 | 1892 |
| 1958 LOperand* external_pointer = UseRegister(instr->external_pointer()); | 1893 LOperand* external_pointer = UseRegister(instr->external_pointer()); |
| 1959 bool val_is_temp_register = array_type == kExternalPixelArray || | 1894 bool val_is_temp_register = |
| 1960 array_type == kExternalFloatArray; | 1895 elements_kind == JSObject::EXTERNAL_PIXEL_ELEMENTS || |
| 1896 elements_kind == JSObject::EXTERNAL_FLOAT_ELEMENTS; |
| 1961 LOperand* val = val_is_temp_register | 1897 LOperand* val = val_is_temp_register |
| 1962 ? UseTempRegister(instr->value()) | 1898 ? UseTempRegister(instr->value()) |
| 1963 : UseRegister(instr->value()); | 1899 : UseRegister(instr->value()); |
| 1964 LOperand* key = UseRegisterOrConstant(instr->key()); | 1900 LOperand* key = UseRegisterOrConstant(instr->key()); |
| 1965 | 1901 |
| 1966 return new LStoreKeyedSpecializedArrayElement(external_pointer, | 1902 return new LStoreKeyedSpecializedArrayElement(external_pointer, |
| 1967 key, | 1903 key, |
| 1968 val); | 1904 val); |
| 1969 } | 1905 } |
| 1970 | 1906 |
| (...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2076 | 2012 |
| 2077 | 2013 |
| 2078 LInstruction* LChunkBuilder::DoParameter(HParameter* instr) { | 2014 LInstruction* LChunkBuilder::DoParameter(HParameter* instr) { |
| 2079 int spill_index = chunk()->GetParameterStackSlot(instr->index()); | 2015 int spill_index = chunk()->GetParameterStackSlot(instr->index()); |
| 2080 return DefineAsSpilled(new LParameter, spill_index); | 2016 return DefineAsSpilled(new LParameter, spill_index); |
| 2081 } | 2017 } |
| 2082 | 2018 |
| 2083 | 2019 |
| 2084 LInstruction* LChunkBuilder::DoUnknownOSRValue(HUnknownOSRValue* instr) { | 2020 LInstruction* LChunkBuilder::DoUnknownOSRValue(HUnknownOSRValue* instr) { |
| 2085 int spill_index = chunk()->GetNextSpillIndex(false); // Not double-width. | 2021 int spill_index = chunk()->GetNextSpillIndex(false); // Not double-width. |
| 2022 if (spill_index > LUnallocated::kMaxFixedIndex) { |
| 2023 Abort("Too many spill slots needed for OSR"); |
| 2024 spill_index = 0; |
| 2025 } |
| 2086 return DefineAsSpilled(new LUnknownOSRValue, spill_index); | 2026 return DefineAsSpilled(new LUnknownOSRValue, spill_index); |
| 2087 } | 2027 } |
| 2088 | 2028 |
| 2089 | 2029 |
| 2090 LInstruction* LChunkBuilder::DoCallStub(HCallStub* instr) { | 2030 LInstruction* LChunkBuilder::DoCallStub(HCallStub* instr) { |
| 2091 argument_count_ -= instr->argument_count(); | 2031 argument_count_ -= instr->argument_count(); |
| 2092 return MarkAsCall(DefineFixed(new LCallStub, rax), instr); | 2032 return MarkAsCall(DefineFixed(new LCallStub, rax), instr); |
| 2093 } | 2033 } |
| 2094 | 2034 |
| 2095 | 2035 |
| (...skipping 21 matching lines...) Expand all Loading... |
| 2117 return MarkAsCall(DefineFixed(result, rax), instr); | 2057 return MarkAsCall(DefineFixed(result, rax), instr); |
| 2118 } | 2058 } |
| 2119 | 2059 |
| 2120 | 2060 |
| 2121 LInstruction* LChunkBuilder::DoTypeof(HTypeof* instr) { | 2061 LInstruction* LChunkBuilder::DoTypeof(HTypeof* instr) { |
| 2122 LTypeof* result = new LTypeof(UseAtStart(instr->value())); | 2062 LTypeof* result = new LTypeof(UseAtStart(instr->value())); |
| 2123 return MarkAsCall(DefineFixed(result, rax), instr); | 2063 return MarkAsCall(DefineFixed(result, rax), instr); |
| 2124 } | 2064 } |
| 2125 | 2065 |
| 2126 | 2066 |
| 2127 LInstruction* LChunkBuilder::DoTypeofIs(HTypeofIs* instr) { | 2067 LInstruction* LChunkBuilder::DoTypeofIsAndBranch(HTypeofIsAndBranch* instr) { |
| 2128 return DefineSameAsFirst(new LTypeofIs(UseRegister(instr->value()))); | 2068 return new LTypeofIsAndBranch(UseTempRegister(instr->value())); |
| 2129 } | 2069 } |
| 2130 | 2070 |
| 2131 | 2071 |
| 2132 LInstruction* LChunkBuilder::DoIsConstructCall(HIsConstructCall* instr) { | 2072 LInstruction* LChunkBuilder::DoIsConstructCallAndBranch( |
| 2133 return DefineAsRegister(new LIsConstructCall); | 2073 HIsConstructCallAndBranch* instr) { |
| 2074 return new LIsConstructCallAndBranch(TempRegister()); |
| 2134 } | 2075 } |
| 2135 | 2076 |
| 2136 | 2077 |
| 2137 LInstruction* LChunkBuilder::DoSimulate(HSimulate* instr) { | 2078 LInstruction* LChunkBuilder::DoSimulate(HSimulate* instr) { |
| 2138 HEnvironment* env = current_block_->last_environment(); | 2079 HEnvironment* env = current_block_->last_environment(); |
| 2139 ASSERT(env != NULL); | 2080 ASSERT(env != NULL); |
| 2140 | 2081 |
| 2141 env->set_ast_id(instr->ast_id()); | 2082 env->set_ast_id(instr->ast_id()); |
| 2142 | 2083 |
| 2143 env->Drop(instr->pop_count()); | 2084 env->Drop(instr->pop_count()); |
| (...skipping 15 matching lines...) Expand all Loading... |
| 2159 set_deoptimization_environment(result->environment()); | 2100 set_deoptimization_environment(result->environment()); |
| 2160 ClearInstructionPendingDeoptimizationEnvironment(); | 2101 ClearInstructionPendingDeoptimizationEnvironment(); |
| 2161 return result; | 2102 return result; |
| 2162 } | 2103 } |
| 2163 | 2104 |
| 2164 return NULL; | 2105 return NULL; |
| 2165 } | 2106 } |
| 2166 | 2107 |
| 2167 | 2108 |
| 2168 LInstruction* LChunkBuilder::DoStackCheck(HStackCheck* instr) { | 2109 LInstruction* LChunkBuilder::DoStackCheck(HStackCheck* instr) { |
| 2169 return MarkAsCall(new LStackCheck, instr); | 2110 if (instr->is_function_entry()) { |
| 2111 return MarkAsCall(new LStackCheck, instr); |
| 2112 } else { |
| 2113 ASSERT(instr->is_backwards_branch()); |
| 2114 return AssignEnvironment(AssignPointerMap(new LStackCheck)); |
| 2115 } |
| 2170 } | 2116 } |
| 2171 | 2117 |
| 2172 | 2118 |
| 2173 LInstruction* LChunkBuilder::DoEnterInlined(HEnterInlined* instr) { | 2119 LInstruction* LChunkBuilder::DoEnterInlined(HEnterInlined* instr) { |
| 2174 HEnvironment* outer = current_block_->last_environment(); | 2120 HEnvironment* outer = current_block_->last_environment(); |
| 2175 HConstant* undefined = graph()->GetConstantUndefined(); | 2121 HConstant* undefined = graph()->GetConstantUndefined(); |
| 2176 HEnvironment* inner = outer->CopyForInlining(instr->closure(), | 2122 HEnvironment* inner = outer->CopyForInlining(instr->closure(), |
| 2177 instr->function(), | 2123 instr->function(), |
| 2178 HEnvironment::LITHIUM, | |
| 2179 undefined, | 2124 undefined, |
| 2180 instr->call_kind()); | 2125 instr->call_kind()); |
| 2181 current_block_->UpdateEnvironment(inner); | 2126 current_block_->UpdateEnvironment(inner); |
| 2182 chunk_->AddInlinedClosure(instr->closure()); | 2127 chunk_->AddInlinedClosure(instr->closure()); |
| 2183 return NULL; | 2128 return NULL; |
| 2184 } | 2129 } |
| 2185 | 2130 |
| 2186 | 2131 |
| 2187 LInstruction* LChunkBuilder::DoLeaveInlined(HLeaveInlined* instr) { | 2132 LInstruction* LChunkBuilder::DoLeaveInlined(HLeaveInlined* instr) { |
| 2188 HEnvironment* outer = current_block_->last_environment()->outer(); | 2133 HEnvironment* outer = current_block_->last_environment()->outer(); |
| 2189 current_block_->UpdateEnvironment(outer); | 2134 current_block_->UpdateEnvironment(outer); |
| 2190 return NULL; | 2135 return NULL; |
| 2191 } | 2136 } |
| 2192 | 2137 |
| 2193 | 2138 |
| 2194 LInstruction* LChunkBuilder::DoIn(HIn* instr) { | 2139 LInstruction* LChunkBuilder::DoIn(HIn* instr) { |
| 2195 LOperand* key = UseOrConstantAtStart(instr->key()); | 2140 LOperand* key = UseOrConstantAtStart(instr->key()); |
| 2196 LOperand* object = UseOrConstantAtStart(instr->object()); | 2141 LOperand* object = UseOrConstantAtStart(instr->object()); |
| 2197 LIn* result = new LIn(key, object); | 2142 LIn* result = new LIn(key, object); |
| 2198 return MarkAsCall(DefineFixed(result, rax), instr); | 2143 return MarkAsCall(DefineFixed(result, rax), instr); |
| 2199 } | 2144 } |
| 2200 | 2145 |
| 2201 | 2146 |
| 2202 } } // namespace v8::internal | 2147 } } // namespace v8::internal |
| 2203 | 2148 |
| 2204 #endif // V8_TARGET_ARCH_X64 | 2149 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |