| 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 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 61 | 61 |
| 62 #ifdef DEBUG | 62 #ifdef DEBUG |
| 63 void LInstruction::VerifyCall() { | 63 void LInstruction::VerifyCall() { |
| 64 // Call instructions can use only fixed registers as temporaries and | 64 // Call instructions can use only fixed registers as temporaries and |
| 65 // outputs because all registers are blocked by the calling convention. | 65 // outputs because all registers are blocked by the calling convention. |
| 66 // Inputs operands must use a fixed register or use-at-start policy or | 66 // Inputs operands must use a fixed register or use-at-start policy or |
| 67 // a non-register policy. | 67 // a non-register policy. |
| 68 ASSERT(Output() == NULL || | 68 ASSERT(Output() == NULL || |
| 69 LUnallocated::cast(Output())->HasFixedPolicy() || | 69 LUnallocated::cast(Output())->HasFixedPolicy() || |
| 70 !LUnallocated::cast(Output())->HasRegisterPolicy()); | 70 !LUnallocated::cast(Output())->HasRegisterPolicy()); |
| 71 for (UseIterator it(this); it.HasNext(); it.Advance()) { | 71 for (UseIterator it(this); !it.Done(); it.Advance()) { |
| 72 LUnallocated* operand = LUnallocated::cast(it.Next()); | 72 LUnallocated* operand = LUnallocated::cast(it.Current()); |
| 73 ASSERT(operand->HasFixedPolicy() || | 73 ASSERT(operand->HasFixedPolicy() || |
| 74 operand->IsUsedAtStart()); | 74 operand->IsUsedAtStart()); |
| 75 } | 75 } |
| 76 for (TempIterator it(this); it.HasNext(); it.Advance()) { | 76 for (TempIterator it(this); !it.Done(); it.Advance()) { |
| 77 LUnallocated* operand = LUnallocated::cast(it.Next()); | 77 LUnallocated* operand = LUnallocated::cast(it.Current()); |
| 78 ASSERT(operand->HasFixedPolicy() ||!operand->HasRegisterPolicy()); | 78 ASSERT(operand->HasFixedPolicy() ||!operand->HasRegisterPolicy()); |
| 79 } | 79 } |
| 80 } | 80 } |
| 81 #endif | 81 #endif |
| 82 | 82 |
| 83 | 83 |
| 84 void LOsrEntry::MarkSpilledDoubleRegister(int allocation_index, | 84 void LOsrEntry::MarkSpilledDoubleRegister(int allocation_index, |
| 85 LOperand* spill_operand) { | 85 LOperand* spill_operand) { |
| 86 ASSERT(spill_operand->IsDoubleStackSlot()); | 86 ASSERT(spill_operand->IsDoubleStackSlot()); |
| 87 ASSERT(double_register_spills_[allocation_index] == NULL); | 87 ASSERT(double_register_spills_[allocation_index] == NULL); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 104 if (HasPointerMap()) { | 104 if (HasPointerMap()) { |
| 105 stream->Add(" "); | 105 stream->Add(" "); |
| 106 pointer_map()->PrintTo(stream); | 106 pointer_map()->PrintTo(stream); |
| 107 } | 107 } |
| 108 } | 108 } |
| 109 | 109 |
| 110 | 110 |
| 111 template<int R, int I, int T> | 111 template<int R, int I, int T> |
| 112 void LTemplateInstruction<R, I, T>::PrintDataTo(StringStream* stream) { | 112 void LTemplateInstruction<R, I, T>::PrintDataTo(StringStream* stream) { |
| 113 stream->Add("= "); | 113 stream->Add("= "); |
| 114 inputs_.PrintOperandsTo(stream); | 114 for (int i = 0; i < inputs_.length(); i++) { |
| 115 if (i > 0) stream->Add(" "); |
| 116 inputs_[i]->PrintTo(stream); |
| 117 } |
| 115 } | 118 } |
| 116 | 119 |
| 117 | 120 |
| 118 template<int R, int I, int T> | 121 template<int R, int I, int T> |
| 119 void LTemplateInstruction<R, I, T>::PrintOutputOperandTo(StringStream* stream) { | 122 void LTemplateInstruction<R, I, T>::PrintOutputOperandTo(StringStream* stream) { |
| 120 results_.PrintOperandsTo(stream); | 123 for (int i = 0; i < results_.length(); i++) { |
| 121 } | |
| 122 | |
| 123 | |
| 124 template<typename T, int N> | |
| 125 void OperandContainer<T, N>::PrintOperandsTo(StringStream* stream) { | |
| 126 for (int i = 0; i < N; i++) { | |
| 127 if (i > 0) stream->Add(" "); | 124 if (i > 0) stream->Add(" "); |
| 128 elems_[i]->PrintTo(stream); | 125 results_[i]->PrintTo(stream); |
| 129 } | 126 } |
| 130 } | 127 } |
| 131 | 128 |
| 132 | 129 |
| 133 void LLabel::PrintDataTo(StringStream* stream) { | 130 void LLabel::PrintDataTo(StringStream* stream) { |
| 134 LGap::PrintDataTo(stream); | 131 LGap::PrintDataTo(stream); |
| 135 LLabel* rep = replacement(); | 132 LLabel* rep = replacement(); |
| 136 if (rep != NULL) { | 133 if (rep != NULL) { |
| 137 stream->Add(" Dead block replaced with B%d", rep->block_id()); | 134 stream->Add(" Dead block replaced with B%d", rep->block_id()); |
| 138 } | 135 } |
| (...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 261 void LClassOfTestAndBranch::PrintDataTo(StringStream* stream) { | 258 void LClassOfTestAndBranch::PrintDataTo(StringStream* stream) { |
| 262 stream->Add("if class_of_test("); | 259 stream->Add("if class_of_test("); |
| 263 InputAt(0)->PrintTo(stream); | 260 InputAt(0)->PrintTo(stream); |
| 264 stream->Add(", \"%o\") then B%d else B%d", | 261 stream->Add(", \"%o\") then B%d else B%d", |
| 265 *hydrogen()->class_name(), | 262 *hydrogen()->class_name(), |
| 266 true_block_id(), | 263 true_block_id(), |
| 267 false_block_id()); | 264 false_block_id()); |
| 268 } | 265 } |
| 269 | 266 |
| 270 | 267 |
| 271 void LTypeofIs::PrintDataTo(StringStream* stream) { | |
| 272 InputAt(0)->PrintTo(stream); | |
| 273 stream->Add(" == \"%s\"", *hydrogen()->type_literal()->ToCString()); | |
| 274 } | |
| 275 | |
| 276 | |
| 277 void LTypeofIsAndBranch::PrintDataTo(StringStream* stream) { | 268 void LTypeofIsAndBranch::PrintDataTo(StringStream* stream) { |
| 278 stream->Add("if typeof "); | 269 stream->Add("if typeof "); |
| 279 InputAt(0)->PrintTo(stream); | 270 InputAt(0)->PrintTo(stream); |
| 280 stream->Add(" == \"%s\" then B%d else B%d", | 271 stream->Add(" == \"%s\" then B%d else B%d", |
| 281 *hydrogen()->type_literal()->ToCString(), | 272 *hydrogen()->type_literal()->ToCString(), |
| 282 true_block_id(), false_block_id()); | 273 true_block_id(), false_block_id()); |
| 283 } | 274 } |
| 284 | 275 |
| 285 | 276 |
| 286 void LCallConstantFunction::PrintDataTo(StringStream* stream) { | 277 void LCallConstantFunction::PrintDataTo(StringStream* stream) { |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 336 } | 327 } |
| 337 | 328 |
| 338 | 329 |
| 339 void LCallNew::PrintDataTo(StringStream* stream) { | 330 void LCallNew::PrintDataTo(StringStream* stream) { |
| 340 stream->Add("= "); | 331 stream->Add("= "); |
| 341 InputAt(0)->PrintTo(stream); | 332 InputAt(0)->PrintTo(stream); |
| 342 stream->Add(" #%d / ", arity()); | 333 stream->Add(" #%d / ", arity()); |
| 343 } | 334 } |
| 344 | 335 |
| 345 | 336 |
| 346 void LClassOfTest::PrintDataTo(StringStream* stream) { | |
| 347 stream->Add("= class_of_test("); | |
| 348 InputAt(0)->PrintTo(stream); | |
| 349 stream->Add(", \"%o\")", *hydrogen()->class_name()); | |
| 350 } | |
| 351 | |
| 352 | |
| 353 void LAccessArgumentsAt::PrintDataTo(StringStream* stream) { | 337 void LAccessArgumentsAt::PrintDataTo(StringStream* stream) { |
| 354 arguments()->PrintTo(stream); | 338 arguments()->PrintTo(stream); |
| 355 | 339 |
| 356 stream->Add(" length "); | 340 stream->Add(" length "); |
| 357 length()->PrintTo(stream); | 341 length()->PrintTo(stream); |
| 358 | 342 |
| 359 stream->Add(" index "); | 343 stream->Add(" index "); |
| 360 index()->PrintTo(stream); | 344 index()->PrintTo(stream); |
| 361 } | 345 } |
| 362 | 346 |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 429 for (int i = 0; i < graph()->blocks()->length(); ++i) { | 413 for (int i = 0; i < graph()->blocks()->length(); ++i) { |
| 430 HBasicBlock* block = graph()->blocks()->at(i); | 414 HBasicBlock* block = graph()->blocks()->at(i); |
| 431 int first = block->first_instruction_index(); | 415 int first = block->first_instruction_index(); |
| 432 int last = block->last_instruction_index(); | 416 int last = block->last_instruction_index(); |
| 433 LInstruction* first_instr = instructions()->at(first); | 417 LInstruction* first_instr = instructions()->at(first); |
| 434 LInstruction* last_instr = instructions()->at(last); | 418 LInstruction* last_instr = instructions()->at(last); |
| 435 | 419 |
| 436 LLabel* label = LLabel::cast(first_instr); | 420 LLabel* label = LLabel::cast(first_instr); |
| 437 if (last_instr->IsGoto()) { | 421 if (last_instr->IsGoto()) { |
| 438 LGoto* goto_instr = LGoto::cast(last_instr); | 422 LGoto* goto_instr = LGoto::cast(last_instr); |
| 439 if (!goto_instr->include_stack_check() && | 423 if (label->IsRedundant() && |
| 440 label->IsRedundant() && | |
| 441 !label->is_loop_header()) { | 424 !label->is_loop_header()) { |
| 442 bool can_eliminate = true; | 425 bool can_eliminate = true; |
| 443 for (int i = first + 1; i < last && can_eliminate; ++i) { | 426 for (int i = first + 1; i < last && can_eliminate; ++i) { |
| 444 LInstruction* cur = instructions()->at(i); | 427 LInstruction* cur = instructions()->at(i); |
| 445 if (cur->IsGap()) { | 428 if (cur->IsGap()) { |
| 446 LGap* gap = LGap::cast(cur); | 429 LGap* gap = LGap::cast(cur); |
| 447 if (!gap->IsRedundant()) { | 430 if (!gap->IsRedundant()) { |
| 448 can_eliminate = false; | 431 can_eliminate = false; |
| 449 } | 432 } |
| 450 } else { | 433 } else { |
| (...skipping 350 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 801 allocator_->RecordTemporary(operand); | 784 allocator_->RecordTemporary(operand); |
| 802 return operand; | 785 return operand; |
| 803 } | 786 } |
| 804 | 787 |
| 805 | 788 |
| 806 LInstruction* LChunkBuilder::DoBlockEntry(HBlockEntry* instr) { | 789 LInstruction* LChunkBuilder::DoBlockEntry(HBlockEntry* instr) { |
| 807 return new LLabel(instr->block()); | 790 return new LLabel(instr->block()); |
| 808 } | 791 } |
| 809 | 792 |
| 810 | 793 |
| 794 LInstruction* LChunkBuilder::DoSoftDeoptimize(HSoftDeoptimize* instr) { |
| 795 return AssignEnvironment(new LDeoptimize); |
| 796 } |
| 797 |
| 798 |
| 811 LInstruction* LChunkBuilder::DoDeoptimize(HDeoptimize* instr) { | 799 LInstruction* LChunkBuilder::DoDeoptimize(HDeoptimize* instr) { |
| 812 return AssignEnvironment(new LDeoptimize); | 800 return AssignEnvironment(new LDeoptimize); |
| 813 } | 801 } |
| 814 | 802 |
| 815 | 803 |
| 816 LInstruction* LChunkBuilder::DoBit(Token::Value op, | 804 LInstruction* LChunkBuilder::DoBit(Token::Value op, |
| 817 HBitwiseBinaryOperation* instr) { | 805 HBitwiseBinaryOperation* instr) { |
| 818 if (instr->representation().IsInteger32()) { | 806 if (instr->representation().IsInteger32()) { |
| 819 ASSERT(instr->left()->representation().IsInteger32()); | 807 ASSERT(instr->left()->representation().IsInteger32()); |
| 820 ASSERT(instr->right()->representation().IsInteger32()); | 808 ASSERT(instr->right()->representation().IsInteger32()); |
| 821 | 809 |
| 822 LOperand* left = UseRegisterAtStart(instr->LeastConstantOperand()); | 810 LOperand* left = UseRegisterAtStart(instr->LeastConstantOperand()); |
| 823 LOperand* right = UseOrConstantAtStart(instr->MostConstantOperand()); | 811 LOperand* right = UseOrConstantAtStart(instr->MostConstantOperand()); |
| 824 return DefineSameAsFirst(new LBitI(op, left, right)); | 812 return DefineAsRegister(new LBitI(op, left, right)); |
| 825 } else { | 813 } else { |
| 826 ASSERT(instr->representation().IsTagged()); | 814 ASSERT(instr->representation().IsTagged()); |
| 827 ASSERT(instr->left()->representation().IsTagged()); | 815 ASSERT(instr->left()->representation().IsTagged()); |
| 828 ASSERT(instr->right()->representation().IsTagged()); | 816 ASSERT(instr->right()->representation().IsTagged()); |
| 829 | 817 |
| 830 LOperand* left = UseFixed(instr->left(), r1); | 818 LOperand* left = UseFixed(instr->left(), r1); |
| 831 LOperand* right = UseFixed(instr->right(), r0); | 819 LOperand* right = UseFixed(instr->right(), r0); |
| 832 LArithmeticT* result = new LArithmeticT(op, left, right); | 820 LArithmeticT* result = new LArithmeticT(op, left, right); |
| 833 return MarkAsCall(DefineFixed(result, r0), instr); | 821 return MarkAsCall(DefineFixed(result, r0), instr); |
| 834 } | 822 } |
| 835 } | 823 } |
| 836 | 824 |
| 837 | 825 |
| 838 LInstruction* LChunkBuilder::DoShift(Token::Value op, | 826 LInstruction* LChunkBuilder::DoShift(Token::Value op, |
| 839 HBitwiseBinaryOperation* instr) { | 827 HBitwiseBinaryOperation* instr) { |
| 840 if (instr->representation().IsTagged()) { | 828 if (instr->representation().IsTagged()) { |
| 841 ASSERT(instr->left()->representation().IsTagged()); | 829 ASSERT(instr->left()->representation().IsTagged()); |
| 842 ASSERT(instr->right()->representation().IsTagged()); | 830 ASSERT(instr->right()->representation().IsTagged()); |
| 843 | 831 |
| 844 LOperand* left = UseFixed(instr->left(), r1); | 832 LOperand* left = UseFixed(instr->left(), r1); |
| 845 LOperand* right = UseFixed(instr->right(), r0); | 833 LOperand* right = UseFixed(instr->right(), r0); |
| 846 LArithmeticT* result = new LArithmeticT(op, left, right); | 834 LArithmeticT* result = new LArithmeticT(op, left, right); |
| 847 return MarkAsCall(DefineFixed(result, r0), instr); | 835 return MarkAsCall(DefineFixed(result, r0), instr); |
| 848 } | 836 } |
| 849 | 837 |
| 850 ASSERT(instr->representation().IsInteger32()); | 838 ASSERT(instr->representation().IsInteger32()); |
| 851 ASSERT(instr->OperandAt(0)->representation().IsInteger32()); | 839 ASSERT(instr->left()->representation().IsInteger32()); |
| 852 ASSERT(instr->OperandAt(1)->representation().IsInteger32()); | 840 ASSERT(instr->right()->representation().IsInteger32()); |
| 853 LOperand* left = UseRegisterAtStart(instr->OperandAt(0)); | 841 LOperand* left = UseRegisterAtStart(instr->left()); |
| 854 | 842 |
| 855 HValue* right_value = instr->OperandAt(1); | 843 HValue* right_value = instr->right(); |
| 856 LOperand* right = NULL; | 844 LOperand* right = NULL; |
| 857 int constant_value = 0; | 845 int constant_value = 0; |
| 858 if (right_value->IsConstant()) { | 846 if (right_value->IsConstant()) { |
| 859 HConstant* constant = HConstant::cast(right_value); | 847 HConstant* constant = HConstant::cast(right_value); |
| 860 right = chunk_->DefineConstantOperand(constant); | 848 right = chunk_->DefineConstantOperand(constant); |
| 861 constant_value = constant->Integer32Value() & 0x1f; | 849 constant_value = constant->Integer32Value() & 0x1f; |
| 862 } else { | 850 } else { |
| 863 right = UseRegister(right_value); | 851 right = UseRegisterAtStart(right_value); |
| 864 } | 852 } |
| 865 | 853 |
| 866 // Shift operations can only deoptimize if we do a logical shift | 854 // Shift operations can only deoptimize if we do a logical shift |
| 867 // by 0 and the result cannot be truncated to int32. | 855 // by 0 and the result cannot be truncated to int32. |
| 868 bool may_deopt = (op == Token::SHR && constant_value == 0); | 856 bool may_deopt = (op == Token::SHR && constant_value == 0); |
| 869 bool does_deopt = false; | 857 bool does_deopt = false; |
| 870 if (may_deopt) { | 858 if (may_deopt) { |
| 871 for (HUseIterator it(instr->uses()); !it.Done(); it.Advance()) { | 859 for (HUseIterator it(instr->uses()); !it.Done(); it.Advance()) { |
| 872 if (!it.value()->CheckFlag(HValue::kTruncatingToInt32)) { | 860 if (!it.value()->CheckFlag(HValue::kTruncatingToInt32)) { |
| 873 does_deopt = true; | 861 does_deopt = true; |
| 874 break; | 862 break; |
| 875 } | 863 } |
| 876 } | 864 } |
| 877 } | 865 } |
| 878 | 866 |
| 879 LInstruction* result = | 867 LInstruction* result = |
| 880 DefineSameAsFirst(new LShiftI(op, left, right, does_deopt)); | 868 DefineAsRegister(new LShiftI(op, left, right, does_deopt)); |
| 881 return does_deopt ? AssignEnvironment(result) : result; | 869 return does_deopt ? AssignEnvironment(result) : result; |
| 882 } | 870 } |
| 883 | 871 |
| 884 | 872 |
| 885 LInstruction* LChunkBuilder::DoArithmeticD(Token::Value op, | 873 LInstruction* LChunkBuilder::DoArithmeticD(Token::Value op, |
| 886 HArithmeticBinaryOperation* instr) { | 874 HArithmeticBinaryOperation* instr) { |
| 887 ASSERT(instr->representation().IsDouble()); | 875 ASSERT(instr->representation().IsDouble()); |
| 888 ASSERT(instr->left()->representation().IsDouble()); | 876 ASSERT(instr->left()->representation().IsDouble()); |
| 889 ASSERT(instr->right()->representation().IsDouble()); | 877 ASSERT(instr->right()->representation().IsDouble()); |
| 890 ASSERT(op != Token::MOD); | 878 ASSERT(op != Token::MOD); |
| 891 LOperand* left = UseRegisterAtStart(instr->left()); | 879 LOperand* left = UseRegisterAtStart(instr->left()); |
| 892 LOperand* right = UseRegisterAtStart(instr->right()); | 880 LOperand* right = UseRegisterAtStart(instr->right()); |
| 893 LArithmeticD* result = new LArithmeticD(op, left, right); | 881 LArithmeticD* result = new LArithmeticD(op, left, right); |
| 894 return DefineSameAsFirst(result); | 882 return DefineAsRegister(result); |
| 895 } | 883 } |
| 896 | 884 |
| 897 | 885 |
| 898 LInstruction* LChunkBuilder::DoArithmeticT(Token::Value op, | 886 LInstruction* LChunkBuilder::DoArithmeticT(Token::Value op, |
| 899 HArithmeticBinaryOperation* instr) { | 887 HArithmeticBinaryOperation* instr) { |
| 900 ASSERT(op == Token::ADD || | 888 ASSERT(op == Token::ADD || |
| 901 op == Token::DIV || | 889 op == Token::DIV || |
| 902 op == Token::MOD || | 890 op == Token::MOD || |
| 903 op == Token::MUL || | 891 op == Token::MUL || |
| 904 op == Token::SUB); | 892 op == Token::SUB); |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 982 if (current->has_position()) position_ = current->position(); | 970 if (current->has_position()) position_ = current->position(); |
| 983 LInstruction* instr = current->CompileToLithium(this); | 971 LInstruction* instr = current->CompileToLithium(this); |
| 984 | 972 |
| 985 if (instr != NULL) { | 973 if (instr != NULL) { |
| 986 if (FLAG_stress_pointer_maps && !instr->HasPointerMap()) { | 974 if (FLAG_stress_pointer_maps && !instr->HasPointerMap()) { |
| 987 instr = AssignPointerMap(instr); | 975 instr = AssignPointerMap(instr); |
| 988 } | 976 } |
| 989 if (FLAG_stress_environments && !instr->HasEnvironment()) { | 977 if (FLAG_stress_environments && !instr->HasEnvironment()) { |
| 990 instr = AssignEnvironment(instr); | 978 instr = AssignEnvironment(instr); |
| 991 } | 979 } |
| 992 if (current->IsTest() && !instr->IsGoto()) { | 980 instr->set_hydrogen_value(current); |
| 993 ASSERT(instr->IsControl()); | |
| 994 HTest* test = HTest::cast(current); | |
| 995 instr->set_hydrogen_value(test->value()); | |
| 996 HBasicBlock* first = test->FirstSuccessor(); | |
| 997 HBasicBlock* second = test->SecondSuccessor(); | |
| 998 ASSERT(first != NULL && second != NULL); | |
| 999 instr->SetBranchTargets(first->block_id(), second->block_id()); | |
| 1000 } else { | |
| 1001 instr->set_hydrogen_value(current); | |
| 1002 } | |
| 1003 | |
| 1004 chunk_->AddInstruction(instr, current_block_); | 981 chunk_->AddInstruction(instr, current_block_); |
| 1005 } | 982 } |
| 1006 current_instruction_ = old_current; | 983 current_instruction_ = old_current; |
| 1007 } | 984 } |
| 1008 | 985 |
| 1009 | 986 |
| 1010 LEnvironment* LChunkBuilder::CreateEnvironment(HEnvironment* hydrogen_env) { | 987 LEnvironment* LChunkBuilder::CreateEnvironment(HEnvironment* hydrogen_env) { |
| 1011 if (hydrogen_env == NULL) return NULL; | 988 if (hydrogen_env == NULL) return NULL; |
| 1012 | 989 |
| 1013 LEnvironment* outer = CreateEnvironment(hydrogen_env->outer()); | 990 LEnvironment* outer = CreateEnvironment(hydrogen_env->outer()); |
| (...skipping 20 matching lines...) Expand all Loading... |
| 1034 op = UseAny(value); | 1011 op = UseAny(value); |
| 1035 } | 1012 } |
| 1036 result->AddValue(op, value->representation()); | 1013 result->AddValue(op, value->representation()); |
| 1037 } | 1014 } |
| 1038 | 1015 |
| 1039 return result; | 1016 return result; |
| 1040 } | 1017 } |
| 1041 | 1018 |
| 1042 | 1019 |
| 1043 LInstruction* LChunkBuilder::DoGoto(HGoto* instr) { | 1020 LInstruction* LChunkBuilder::DoGoto(HGoto* instr) { |
| 1044 LInstruction* result = new LGoto(instr->FirstSuccessor()->block_id(), | 1021 return new LGoto(instr->FirstSuccessor()->block_id()); |
| 1045 instr->include_stack_check()); | |
| 1046 if (instr->include_stack_check()) result = AssignPointerMap(result); | |
| 1047 return result; | |
| 1048 } | 1022 } |
| 1049 | 1023 |
| 1050 | 1024 |
| 1051 LInstruction* LChunkBuilder::DoTest(HTest* instr) { | 1025 LInstruction* LChunkBuilder::DoBranch(HBranch* instr) { |
| 1052 HValue* v = instr->value(); | 1026 HValue* v = instr->value(); |
| 1053 if (!v->EmitAtUses()) { | 1027 if (v->EmitAtUses()) { |
| 1054 return new LBranch(UseRegisterAtStart(v)); | |
| 1055 } else if (v->IsClassOfTest()) { | |
| 1056 HClassOfTest* compare = HClassOfTest::cast(v); | |
| 1057 ASSERT(compare->value()->representation().IsTagged()); | |
| 1058 return new LClassOfTestAndBranch(UseTempRegister(compare->value()), | |
| 1059 TempRegister()); | |
| 1060 } else if (v->IsCompare()) { | |
| 1061 HCompare* compare = HCompare::cast(v); | |
| 1062 Token::Value op = compare->token(); | |
| 1063 HValue* left = compare->left(); | |
| 1064 HValue* right = compare->right(); | |
| 1065 Representation r = compare->GetInputRepresentation(); | |
| 1066 if (r.IsInteger32()) { | |
| 1067 ASSERT(left->representation().IsInteger32()); | |
| 1068 ASSERT(right->representation().IsInteger32()); | |
| 1069 return new LCmpIDAndBranch(UseRegisterAtStart(left), | |
| 1070 UseRegisterAtStart(right)); | |
| 1071 } else if (r.IsDouble()) { | |
| 1072 ASSERT(left->representation().IsDouble()); | |
| 1073 ASSERT(right->representation().IsDouble()); | |
| 1074 return new LCmpIDAndBranch(UseRegisterAtStart(left), | |
| 1075 UseRegisterAtStart(right)); | |
| 1076 } else { | |
| 1077 ASSERT(left->representation().IsTagged()); | |
| 1078 ASSERT(right->representation().IsTagged()); | |
| 1079 bool reversed = op == Token::GT || op == Token::LTE; | |
| 1080 LOperand* left_operand = UseFixed(left, reversed ? r0 : r1); | |
| 1081 LOperand* right_operand = UseFixed(right, reversed ? r1 : r0); | |
| 1082 LInstruction* result = new LCmpTAndBranch(left_operand, right_operand); | |
| 1083 return MarkAsCall(result, instr); | |
| 1084 } | |
| 1085 } else if (v->IsIsSmi()) { | |
| 1086 HIsSmi* compare = HIsSmi::cast(v); | |
| 1087 ASSERT(compare->value()->representation().IsTagged()); | |
| 1088 return new LIsSmiAndBranch(Use(compare->value())); | |
| 1089 } else if (v->IsIsUndetectable()) { | |
| 1090 HIsUndetectable* compare = HIsUndetectable::cast(v); | |
| 1091 ASSERT(compare->value()->representation().IsTagged()); | |
| 1092 return new LIsUndetectableAndBranch(UseRegisterAtStart(compare->value()), | |
| 1093 TempRegister()); | |
| 1094 } else if (v->IsHasInstanceType()) { | |
| 1095 HHasInstanceType* compare = HHasInstanceType::cast(v); | |
| 1096 ASSERT(compare->value()->representation().IsTagged()); | |
| 1097 return new LHasInstanceTypeAndBranch(UseRegisterAtStart(compare->value())); | |
| 1098 } else if (v->IsHasCachedArrayIndex()) { | |
| 1099 HHasCachedArrayIndex* compare = HHasCachedArrayIndex::cast(v); | |
| 1100 ASSERT(compare->value()->representation().IsTagged()); | |
| 1101 return new LHasCachedArrayIndexAndBranch( | |
| 1102 UseRegisterAtStart(compare->value())); | |
| 1103 } else if (v->IsIsNull()) { | |
| 1104 HIsNull* compare = HIsNull::cast(v); | |
| 1105 ASSERT(compare->value()->representation().IsTagged()); | |
| 1106 return new LIsNullAndBranch(UseRegisterAtStart(compare->value())); | |
| 1107 } else if (v->IsIsObject()) { | |
| 1108 HIsObject* compare = HIsObject::cast(v); | |
| 1109 ASSERT(compare->value()->representation().IsTagged()); | |
| 1110 LOperand* temp = TempRegister(); | |
| 1111 return new LIsObjectAndBranch(UseRegisterAtStart(compare->value()), temp); | |
| 1112 } else if (v->IsCompareJSObjectEq()) { | |
| 1113 HCompareJSObjectEq* compare = HCompareJSObjectEq::cast(v); | |
| 1114 return new LCmpJSObjectEqAndBranch(UseRegisterAtStart(compare->left()), | |
| 1115 UseRegisterAtStart(compare->right())); | |
| 1116 } else if (v->IsCompareSymbolEq()) { | |
| 1117 HCompareSymbolEq* compare = HCompareSymbolEq::cast(v); | |
| 1118 return new LCmpSymbolEqAndBranch(UseRegisterAtStart(compare->left()), | |
| 1119 UseRegisterAtStart(compare->right())); | |
| 1120 } else if (v->IsInstanceOf()) { | |
| 1121 HInstanceOf* instance_of = HInstanceOf::cast(v); | |
| 1122 LInstruction* result = | |
| 1123 new LInstanceOfAndBranch(UseFixed(instance_of->left(), r0), | |
| 1124 UseFixed(instance_of->right(), r1)); | |
| 1125 return MarkAsCall(result, instr); | |
| 1126 } else if (v->IsTypeofIs()) { | |
| 1127 HTypeofIs* typeof_is = HTypeofIs::cast(v); | |
| 1128 return new LTypeofIsAndBranch(UseTempRegister(typeof_is->value())); | |
| 1129 } else if (v->IsIsConstructCall()) { | |
| 1130 return new LIsConstructCallAndBranch(TempRegister()); | |
| 1131 } else if (v->IsConstant()) { | |
| 1132 HBasicBlock* successor = HConstant::cast(v)->ToBoolean() | 1028 HBasicBlock* successor = HConstant::cast(v)->ToBoolean() |
| 1133 ? instr->FirstSuccessor() | 1029 ? instr->FirstSuccessor() |
| 1134 : instr->SecondSuccessor(); | 1030 : instr->SecondSuccessor(); |
| 1135 return new LGoto(successor->block_id()); | 1031 return new LGoto(successor->block_id()); |
| 1136 } else { | |
| 1137 Abort("Undefined compare before branch"); | |
| 1138 return NULL; | |
| 1139 } | 1032 } |
| 1033 return new LBranch(UseRegisterAtStart(v)); |
| 1140 } | 1034 } |
| 1141 | 1035 |
| 1142 | 1036 |
| 1143 | 1037 |
| 1144 LInstruction* LChunkBuilder::DoCompareMap(HCompareMap* instr) { | 1038 LInstruction* LChunkBuilder::DoCompareMap(HCompareMap* instr) { |
| 1145 ASSERT(instr->value()->representation().IsTagged()); | 1039 ASSERT(instr->value()->representation().IsTagged()); |
| 1146 LOperand* value = UseRegisterAtStart(instr->value()); | 1040 LOperand* value = UseRegisterAtStart(instr->value()); |
| 1147 LOperand* temp = TempRegister(); | 1041 LOperand* temp = TempRegister(); |
| 1148 return new LCmpMapAndBranch(value, temp); | 1042 return new LCmpMapAndBranch(value, temp); |
| 1149 } | 1043 } |
| (...skipping 13 matching lines...) Expand all Loading... |
| 1163 LInstanceOf* result = | 1057 LInstanceOf* result = |
| 1164 new LInstanceOf(UseFixed(instr->left(), r0), | 1058 new LInstanceOf(UseFixed(instr->left(), r0), |
| 1165 UseFixed(instr->right(), r1)); | 1059 UseFixed(instr->right(), r1)); |
| 1166 return MarkAsCall(DefineFixed(result, r0), instr); | 1060 return MarkAsCall(DefineFixed(result, r0), instr); |
| 1167 } | 1061 } |
| 1168 | 1062 |
| 1169 | 1063 |
| 1170 LInstruction* LChunkBuilder::DoInstanceOfKnownGlobal( | 1064 LInstruction* LChunkBuilder::DoInstanceOfKnownGlobal( |
| 1171 HInstanceOfKnownGlobal* instr) { | 1065 HInstanceOfKnownGlobal* instr) { |
| 1172 LInstanceOfKnownGlobal* result = | 1066 LInstanceOfKnownGlobal* result = |
| 1173 new LInstanceOfKnownGlobal(UseFixed(instr->value(), r0), FixedTemp(r4)); | 1067 new LInstanceOfKnownGlobal(UseFixed(instr->left(), r0), FixedTemp(r4)); |
| 1174 return MarkAsCall(DefineFixed(result, r0), instr); | 1068 return MarkAsCall(DefineFixed(result, r0), instr); |
| 1175 } | 1069 } |
| 1176 | 1070 |
| 1177 | 1071 |
| 1178 LInstruction* LChunkBuilder::DoApplyArguments(HApplyArguments* instr) { | 1072 LInstruction* LChunkBuilder::DoApplyArguments(HApplyArguments* instr) { |
| 1179 LOperand* function = UseFixed(instr->function(), r1); | 1073 LOperand* function = UseFixed(instr->function(), r1); |
| 1180 LOperand* receiver = UseFixed(instr->receiver(), r0); | 1074 LOperand* receiver = UseFixed(instr->receiver(), r0); |
| 1181 LOperand* length = UseFixed(instr->length(), r2); | 1075 LOperand* length = UseFixed(instr->length(), r2); |
| 1182 LOperand* elements = UseFixed(instr->elements(), r3); | 1076 LOperand* elements = UseFixed(instr->elements(), r3); |
| 1183 LApplyArguments* result = new LApplyArguments(function, | 1077 LApplyArguments* result = new LApplyArguments(function, |
| 1184 receiver, | 1078 receiver, |
| 1185 length, | 1079 length, |
| 1186 elements); | 1080 elements); |
| 1187 return MarkAsCall(DefineFixed(result, r0), instr, CAN_DEOPTIMIZE_EAGERLY); | 1081 return MarkAsCall(DefineFixed(result, r0), instr, CAN_DEOPTIMIZE_EAGERLY); |
| 1188 } | 1082 } |
| 1189 | 1083 |
| 1190 | 1084 |
| 1191 LInstruction* LChunkBuilder::DoPushArgument(HPushArgument* instr) { | 1085 LInstruction* LChunkBuilder::DoPushArgument(HPushArgument* instr) { |
| 1192 ++argument_count_; | 1086 ++argument_count_; |
| 1193 LOperand* argument = Use(instr->argument()); | 1087 LOperand* argument = Use(instr->argument()); |
| 1194 return new LPushArgument(argument); | 1088 return new LPushArgument(argument); |
| 1195 } | 1089 } |
| 1196 | 1090 |
| 1197 | 1091 |
| 1092 LInstruction* LChunkBuilder::DoThisFunction(HThisFunction* instr) { |
| 1093 return instr->HasNoUses() ? NULL : DefineAsRegister(new LThisFunction); |
| 1094 } |
| 1095 |
| 1096 |
| 1198 LInstruction* LChunkBuilder::DoContext(HContext* instr) { | 1097 LInstruction* LChunkBuilder::DoContext(HContext* instr) { |
| 1199 return instr->HasNoUses() ? NULL : DefineAsRegister(new LContext); | 1098 return instr->HasNoUses() ? NULL : DefineAsRegister(new LContext); |
| 1200 } | 1099 } |
| 1201 | 1100 |
| 1202 | 1101 |
| 1203 LInstruction* LChunkBuilder::DoOuterContext(HOuterContext* instr) { | 1102 LInstruction* LChunkBuilder::DoOuterContext(HOuterContext* instr) { |
| 1204 LOperand* context = UseRegisterAtStart(instr->value()); | 1103 LOperand* context = UseRegisterAtStart(instr->value()); |
| 1205 return DefineAsRegister(new LOuterContext(context)); | 1104 return DefineAsRegister(new LOuterContext(context)); |
| 1206 } | 1105 } |
| 1207 | 1106 |
| (...skipping 30 matching lines...) Expand all Loading... |
| 1238 if (op == kMathLog || op == kMathSin || op == kMathCos) { | 1137 if (op == kMathLog || op == kMathSin || op == kMathCos) { |
| 1239 LOperand* input = UseFixedDouble(instr->value(), d2); | 1138 LOperand* input = UseFixedDouble(instr->value(), d2); |
| 1240 LUnaryMathOperation* result = new LUnaryMathOperation(input, NULL); | 1139 LUnaryMathOperation* result = new LUnaryMathOperation(input, NULL); |
| 1241 return MarkAsCall(DefineFixedDouble(result, d2), instr); | 1140 return MarkAsCall(DefineFixedDouble(result, d2), instr); |
| 1242 } else { | 1141 } else { |
| 1243 LOperand* input = UseRegisterAtStart(instr->value()); | 1142 LOperand* input = UseRegisterAtStart(instr->value()); |
| 1244 LOperand* temp = (op == kMathFloor) ? TempRegister() : NULL; | 1143 LOperand* temp = (op == kMathFloor) ? TempRegister() : NULL; |
| 1245 LUnaryMathOperation* result = new LUnaryMathOperation(input, temp); | 1144 LUnaryMathOperation* result = new LUnaryMathOperation(input, temp); |
| 1246 switch (op) { | 1145 switch (op) { |
| 1247 case kMathAbs: | 1146 case kMathAbs: |
| 1248 return AssignEnvironment(AssignPointerMap(DefineSameAsFirst(result))); | 1147 return AssignEnvironment(AssignPointerMap(DefineAsRegister(result))); |
| 1249 case kMathFloor: | 1148 case kMathFloor: |
| 1250 return AssignEnvironment(AssignPointerMap(DefineAsRegister(result))); | 1149 return AssignEnvironment(AssignPointerMap(DefineAsRegister(result))); |
| 1251 case kMathSqrt: | 1150 case kMathSqrt: |
| 1252 return DefineSameAsFirst(result); | 1151 return DefineAsRegister(result); |
| 1253 case kMathRound: | 1152 case kMathRound: |
| 1254 return AssignEnvironment(DefineAsRegister(result)); | 1153 return AssignEnvironment(DefineAsRegister(result)); |
| 1255 case kMathPowHalf: | 1154 case kMathPowHalf: |
| 1256 return DefineSameAsFirst(result); | 1155 return DefineAsRegister(result); |
| 1257 default: | 1156 default: |
| 1258 UNREACHABLE(); | 1157 UNREACHABLE(); |
| 1259 return NULL; | 1158 return NULL; |
| 1260 } | 1159 } |
| 1261 } | 1160 } |
| 1262 } | 1161 } |
| 1263 | 1162 |
| 1264 | 1163 |
| 1265 LInstruction* LChunkBuilder::DoCallKeyed(HCallKeyed* instr) { | 1164 LInstruction* LChunkBuilder::DoCallKeyed(HCallKeyed* instr) { |
| 1266 ASSERT(instr->key()->representation().IsTagged()); | 1165 ASSERT(instr->key()->representation().IsTagged()); |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1324 | 1223 |
| 1325 | 1224 |
| 1326 LInstruction* LChunkBuilder::DoBitAnd(HBitAnd* instr) { | 1225 LInstruction* LChunkBuilder::DoBitAnd(HBitAnd* instr) { |
| 1327 return DoBit(Token::BIT_AND, instr); | 1226 return DoBit(Token::BIT_AND, instr); |
| 1328 } | 1227 } |
| 1329 | 1228 |
| 1330 | 1229 |
| 1331 LInstruction* LChunkBuilder::DoBitNot(HBitNot* instr) { | 1230 LInstruction* LChunkBuilder::DoBitNot(HBitNot* instr) { |
| 1332 ASSERT(instr->value()->representation().IsInteger32()); | 1231 ASSERT(instr->value()->representation().IsInteger32()); |
| 1333 ASSERT(instr->representation().IsInteger32()); | 1232 ASSERT(instr->representation().IsInteger32()); |
| 1334 return DefineSameAsFirst(new LBitNotI(UseRegisterAtStart(instr->value()))); | 1233 return DefineAsRegister(new LBitNotI(UseRegisterAtStart(instr->value()))); |
| 1335 } | 1234 } |
| 1336 | 1235 |
| 1337 | 1236 |
| 1338 LInstruction* LChunkBuilder::DoBitOr(HBitOr* instr) { | 1237 LInstruction* LChunkBuilder::DoBitOr(HBitOr* instr) { |
| 1339 return DoBit(Token::BIT_OR, instr); | 1238 return DoBit(Token::BIT_OR, instr); |
| 1340 } | 1239 } |
| 1341 | 1240 |
| 1342 | 1241 |
| 1343 LInstruction* LChunkBuilder::DoBitXor(HBitXor* instr) { | 1242 LInstruction* LChunkBuilder::DoBitXor(HBitXor* instr) { |
| 1344 return DoBit(Token::BIT_XOR, instr); | 1243 return DoBit(Token::BIT_XOR, instr); |
| (...skipping 24 matching lines...) Expand all Loading... |
| 1369 ASSERT(instr->left()->representation().IsInteger32()); | 1268 ASSERT(instr->left()->representation().IsInteger32()); |
| 1370 ASSERT(instr->right()->representation().IsInteger32()); | 1269 ASSERT(instr->right()->representation().IsInteger32()); |
| 1371 | 1270 |
| 1372 LModI* mod; | 1271 LModI* mod; |
| 1373 if (instr->HasPowerOf2Divisor()) { | 1272 if (instr->HasPowerOf2Divisor()) { |
| 1374 ASSERT(!instr->CheckFlag(HValue::kCanBeDivByZero)); | 1273 ASSERT(!instr->CheckFlag(HValue::kCanBeDivByZero)); |
| 1375 LOperand* value = UseRegisterAtStart(instr->left()); | 1274 LOperand* value = UseRegisterAtStart(instr->left()); |
| 1376 mod = new LModI(value, UseOrConstant(instr->right())); | 1275 mod = new LModI(value, UseOrConstant(instr->right())); |
| 1377 } else { | 1276 } else { |
| 1378 LOperand* dividend = UseRegister(instr->left()); | 1277 LOperand* dividend = UseRegister(instr->left()); |
| 1379 LOperand* divisor = UseRegisterAtStart(instr->right()); | 1278 LOperand* divisor = UseRegister(instr->right()); |
| 1380 mod = new LModI(dividend, | 1279 mod = new LModI(dividend, |
| 1381 divisor, | 1280 divisor, |
| 1382 TempRegister(), | 1281 TempRegister(), |
| 1383 FixedTemp(d1), | 1282 FixedTemp(d10), |
| 1384 FixedTemp(d2)); | 1283 FixedTemp(d11)); |
| 1385 } | 1284 } |
| 1386 | 1285 |
| 1387 return AssignEnvironment(DefineSameAsFirst(mod)); | 1286 if (instr->CheckFlag(HValue::kBailoutOnMinusZero) || |
| 1287 instr->CheckFlag(HValue::kCanBeDivByZero)) { |
| 1288 return AssignEnvironment(DefineAsRegister(mod)); |
| 1289 } else { |
| 1290 return DefineAsRegister(mod); |
| 1291 } |
| 1388 } else if (instr->representation().IsTagged()) { | 1292 } else if (instr->representation().IsTagged()) { |
| 1389 return DoArithmeticT(Token::MOD, instr); | 1293 return DoArithmeticT(Token::MOD, instr); |
| 1390 } else { | 1294 } else { |
| 1391 ASSERT(instr->representation().IsDouble()); | 1295 ASSERT(instr->representation().IsDouble()); |
| 1392 // We call a C function for double modulo. It can't trigger a GC. | 1296 // We call a C function for double modulo. It can't trigger a GC. |
| 1393 // We need to use fixed result register for the call. | 1297 // We need to use fixed result register for the call. |
| 1394 // TODO(fschneider): Allow any register as input registers. | 1298 // TODO(fschneider): Allow any register as input registers. |
| 1395 LOperand* left = UseFixedDouble(instr->left(), d1); | 1299 LOperand* left = UseFixedDouble(instr->left(), d1); |
| 1396 LOperand* right = UseFixedDouble(instr->right(), d2); | 1300 LOperand* right = UseFixedDouble(instr->right(), d2); |
| 1397 LArithmeticD* result = new LArithmeticD(Token::MOD, left, right); | 1301 LArithmeticD* result = new LArithmeticD(Token::MOD, left, right); |
| 1398 return MarkAsCall(DefineFixedDouble(result, d1), instr); | 1302 return MarkAsCall(DefineFixedDouble(result, d1), instr); |
| 1399 } | 1303 } |
| 1400 } | 1304 } |
| 1401 | 1305 |
| 1402 | 1306 |
| 1403 LInstruction* LChunkBuilder::DoMul(HMul* instr) { | 1307 LInstruction* LChunkBuilder::DoMul(HMul* instr) { |
| 1404 if (instr->representation().IsInteger32()) { | 1308 if (instr->representation().IsInteger32()) { |
| 1405 ASSERT(instr->left()->representation().IsInteger32()); | 1309 ASSERT(instr->left()->representation().IsInteger32()); |
| 1406 ASSERT(instr->right()->representation().IsInteger32()); | 1310 ASSERT(instr->right()->representation().IsInteger32()); |
| 1407 LOperand* left = UseRegisterAtStart(instr->LeastConstantOperand()); | 1311 LOperand* left; |
| 1408 LOperand* right = UseOrConstant(instr->MostConstantOperand()); | 1312 LOperand* right = UseOrConstant(instr->MostConstantOperand()); |
| 1409 LOperand* temp = NULL; | 1313 LOperand* temp = NULL; |
| 1410 if (instr->CheckFlag(HValue::kBailoutOnMinusZero)) { | 1314 if (instr->CheckFlag(HValue::kBailoutOnMinusZero) && |
| 1315 (instr->CheckFlag(HValue::kCanOverflow) || |
| 1316 !right->IsConstantOperand())) { |
| 1317 left = UseRegister(instr->LeastConstantOperand()); |
| 1411 temp = TempRegister(); | 1318 temp = TempRegister(); |
| 1319 } else { |
| 1320 left = UseRegisterAtStart(instr->LeastConstantOperand()); |
| 1412 } | 1321 } |
| 1413 LMulI* mul = new LMulI(left, right, temp); | 1322 return AssignEnvironment(DefineAsRegister(new LMulI(left, right, temp))); |
| 1414 return AssignEnvironment(DefineSameAsFirst(mul)); | 1323 |
| 1415 } else if (instr->representation().IsDouble()) { | 1324 } else if (instr->representation().IsDouble()) { |
| 1416 return DoArithmeticD(Token::MUL, instr); | 1325 return DoArithmeticD(Token::MUL, instr); |
| 1326 |
| 1417 } else { | 1327 } else { |
| 1418 return DoArithmeticT(Token::MUL, instr); | 1328 return DoArithmeticT(Token::MUL, instr); |
| 1419 } | 1329 } |
| 1420 } | 1330 } |
| 1421 | 1331 |
| 1422 | 1332 |
| 1423 LInstruction* LChunkBuilder::DoSub(HSub* instr) { | 1333 LInstruction* LChunkBuilder::DoSub(HSub* instr) { |
| 1424 if (instr->representation().IsInteger32()) { | 1334 if (instr->representation().IsInteger32()) { |
| 1425 ASSERT(instr->left()->representation().IsInteger32()); | 1335 ASSERT(instr->left()->representation().IsInteger32()); |
| 1426 ASSERT(instr->right()->representation().IsInteger32()); | 1336 ASSERT(instr->right()->representation().IsInteger32()); |
| 1427 LOperand* left = UseRegisterAtStart(instr->left()); | 1337 LOperand* left = UseRegisterAtStart(instr->left()); |
| 1428 LOperand* right = UseOrConstantAtStart(instr->right()); | 1338 LOperand* right = UseOrConstantAtStart(instr->right()); |
| 1429 LSubI* sub = new LSubI(left, right); | 1339 LSubI* sub = new LSubI(left, right); |
| 1430 LInstruction* result = DefineSameAsFirst(sub); | 1340 LInstruction* result = DefineAsRegister(sub); |
| 1431 if (instr->CheckFlag(HValue::kCanOverflow)) { | 1341 if (instr->CheckFlag(HValue::kCanOverflow)) { |
| 1432 result = AssignEnvironment(result); | 1342 result = AssignEnvironment(result); |
| 1433 } | 1343 } |
| 1434 return result; | 1344 return result; |
| 1435 } else if (instr->representation().IsDouble()) { | 1345 } else if (instr->representation().IsDouble()) { |
| 1436 return DoArithmeticD(Token::SUB, instr); | 1346 return DoArithmeticD(Token::SUB, instr); |
| 1437 } else { | 1347 } else { |
| 1438 return DoArithmeticT(Token::SUB, instr); | 1348 return DoArithmeticT(Token::SUB, instr); |
| 1439 } | 1349 } |
| 1440 } | 1350 } |
| 1441 | 1351 |
| 1442 | 1352 |
| 1443 LInstruction* LChunkBuilder::DoAdd(HAdd* instr) { | 1353 LInstruction* LChunkBuilder::DoAdd(HAdd* instr) { |
| 1444 if (instr->representation().IsInteger32()) { | 1354 if (instr->representation().IsInteger32()) { |
| 1445 ASSERT(instr->left()->representation().IsInteger32()); | 1355 ASSERT(instr->left()->representation().IsInteger32()); |
| 1446 ASSERT(instr->right()->representation().IsInteger32()); | 1356 ASSERT(instr->right()->representation().IsInteger32()); |
| 1447 LOperand* left = UseRegisterAtStart(instr->LeastConstantOperand()); | 1357 LOperand* left = UseRegisterAtStart(instr->LeastConstantOperand()); |
| 1448 LOperand* right = UseOrConstantAtStart(instr->MostConstantOperand()); | 1358 LOperand* right = UseOrConstantAtStart(instr->MostConstantOperand()); |
| 1449 LAddI* add = new LAddI(left, right); | 1359 LAddI* add = new LAddI(left, right); |
| 1450 LInstruction* result = DefineSameAsFirst(add); | 1360 LInstruction* result = DefineAsRegister(add); |
| 1451 if (instr->CheckFlag(HValue::kCanOverflow)) { | 1361 if (instr->CheckFlag(HValue::kCanOverflow)) { |
| 1452 result = AssignEnvironment(result); | 1362 result = AssignEnvironment(result); |
| 1453 } | 1363 } |
| 1454 return result; | 1364 return result; |
| 1455 } else if (instr->representation().IsDouble()) { | 1365 } else if (instr->representation().IsDouble()) { |
| 1456 return DoArithmeticD(Token::ADD, instr); | 1366 return DoArithmeticD(Token::ADD, instr); |
| 1457 } else { | 1367 } else { |
| 1458 ASSERT(instr->representation().IsTagged()); | 1368 ASSERT(instr->representation().IsTagged()); |
| 1459 return DoArithmeticT(Token::ADD, instr); | 1369 return DoArithmeticT(Token::ADD, instr); |
| 1460 } | 1370 } |
| (...skipping 10 matching lines...) Expand all Loading... |
| 1471 LOperand* right = exponent_type.IsDouble() ? | 1381 LOperand* right = exponent_type.IsDouble() ? |
| 1472 UseFixedDouble(instr->right(), d2) : | 1382 UseFixedDouble(instr->right(), d2) : |
| 1473 UseFixed(instr->right(), r0); | 1383 UseFixed(instr->right(), r0); |
| 1474 LPower* result = new LPower(left, right); | 1384 LPower* result = new LPower(left, right); |
| 1475 return MarkAsCall(DefineFixedDouble(result, d3), | 1385 return MarkAsCall(DefineFixedDouble(result, d3), |
| 1476 instr, | 1386 instr, |
| 1477 CAN_DEOPTIMIZE_EAGERLY); | 1387 CAN_DEOPTIMIZE_EAGERLY); |
| 1478 } | 1388 } |
| 1479 | 1389 |
| 1480 | 1390 |
| 1481 LInstruction* LChunkBuilder::DoCompare(HCompare* instr) { | 1391 LInstruction* LChunkBuilder::DoCompareGeneric(HCompareGeneric* instr) { |
| 1482 Token::Value op = instr->token(); | 1392 Token::Value op = instr->token(); |
| 1483 Representation r = instr->GetInputRepresentation(); | 1393 Representation r = instr->GetInputRepresentation(); |
| 1394 ASSERT(instr->left()->representation().IsTagged()); |
| 1395 ASSERT(instr->right()->representation().IsTagged()); |
| 1396 bool reversed = (op == Token::GT || op == Token::LTE); |
| 1397 LOperand* left = UseFixed(instr->left(), reversed ? r0 : r1); |
| 1398 LOperand* right = UseFixed(instr->right(), reversed ? r1 : r0); |
| 1399 LCmpT* result = new LCmpT(left, right); |
| 1400 return MarkAsCall(DefineFixed(result, r0), instr); |
| 1401 } |
| 1402 |
| 1403 |
| 1404 LInstruction* LChunkBuilder::DoCompareIDAndBranch( |
| 1405 HCompareIDAndBranch* instr) { |
| 1406 Representation r = instr->GetInputRepresentation(); |
| 1484 if (r.IsInteger32()) { | 1407 if (r.IsInteger32()) { |
| 1485 ASSERT(instr->left()->representation().IsInteger32()); | 1408 ASSERT(instr->left()->representation().IsInteger32()); |
| 1486 ASSERT(instr->right()->representation().IsInteger32()); | 1409 ASSERT(instr->right()->representation().IsInteger32()); |
| 1487 LOperand* left = UseRegisterAtStart(instr->left()); | 1410 LOperand* left = UseRegisterAtStart(instr->left()); |
| 1488 LOperand* right = UseRegisterAtStart(instr->right()); | 1411 LOperand* right = UseRegisterAtStart(instr->right()); |
| 1489 return DefineAsRegister(new LCmpID(left, right)); | 1412 return new LCmpIDAndBranch(left, right); |
| 1490 } else if (r.IsDouble()) { | 1413 } else { |
| 1414 ASSERT(r.IsDouble()); |
| 1491 ASSERT(instr->left()->representation().IsDouble()); | 1415 ASSERT(instr->left()->representation().IsDouble()); |
| 1492 ASSERT(instr->right()->representation().IsDouble()); | 1416 ASSERT(instr->right()->representation().IsDouble()); |
| 1493 LOperand* left = UseRegisterAtStart(instr->left()); | 1417 LOperand* left = UseRegisterAtStart(instr->left()); |
| 1494 LOperand* right = UseRegisterAtStart(instr->right()); | 1418 LOperand* right = UseRegisterAtStart(instr->right()); |
| 1495 return DefineAsRegister(new LCmpID(left, right)); | 1419 return new LCmpIDAndBranch(left, right); |
| 1496 } else { | |
| 1497 ASSERT(instr->left()->representation().IsTagged()); | |
| 1498 ASSERT(instr->right()->representation().IsTagged()); | |
| 1499 bool reversed = (op == Token::GT || op == Token::LTE); | |
| 1500 LOperand* left = UseFixed(instr->left(), reversed ? r0 : r1); | |
| 1501 LOperand* right = UseFixed(instr->right(), reversed ? r1 : r0); | |
| 1502 LCmpT* result = new LCmpT(left, right); | |
| 1503 return MarkAsCall(DefineFixed(result, r0), instr); | |
| 1504 } | 1420 } |
| 1505 } | 1421 } |
| 1506 | 1422 |
| 1507 | 1423 |
| 1508 LInstruction* LChunkBuilder::DoCompareJSObjectEq( | 1424 LInstruction* LChunkBuilder::DoCompareObjectEqAndBranch( |
| 1509 HCompareJSObjectEq* instr) { | 1425 HCompareObjectEqAndBranch* instr) { |
| 1510 LOperand* left = UseRegisterAtStart(instr->left()); | 1426 LOperand* left = UseRegisterAtStart(instr->left()); |
| 1511 LOperand* right = UseRegisterAtStart(instr->right()); | 1427 LOperand* right = UseRegisterAtStart(instr->right()); |
| 1512 LCmpJSObjectEq* result = new LCmpJSObjectEq(left, right); | 1428 return new LCmpObjectEqAndBranch(left, right); |
| 1513 return DefineAsRegister(result); | |
| 1514 } | 1429 } |
| 1515 | 1430 |
| 1516 | 1431 |
| 1517 LInstruction* LChunkBuilder::DoCompareSymbolEq( | 1432 LInstruction* LChunkBuilder::DoCompareConstantEqAndBranch( |
| 1518 HCompareSymbolEq* instr) { | 1433 HCompareConstantEqAndBranch* instr) { |
| 1519 LOperand* left = UseRegisterAtStart(instr->left()); | 1434 return new LCmpConstantEqAndBranch(UseRegisterAtStart(instr->value())); |
| 1520 LOperand* right = UseRegisterAtStart(instr->right()); | |
| 1521 LCmpSymbolEq* result = new LCmpSymbolEq(left, right); | |
| 1522 return DefineAsRegister(result); | |
| 1523 } | 1435 } |
| 1524 | 1436 |
| 1525 | 1437 |
| 1526 LInstruction* LChunkBuilder::DoIsNull(HIsNull* instr) { | 1438 LInstruction* LChunkBuilder::DoIsNullAndBranch(HIsNullAndBranch* instr) { |
| 1527 ASSERT(instr->value()->representation().IsTagged()); | 1439 ASSERT(instr->value()->representation().IsTagged()); |
| 1528 LOperand* value = UseRegisterAtStart(instr->value()); | 1440 return new LIsNullAndBranch(UseRegisterAtStart(instr->value())); |
| 1529 | |
| 1530 return DefineAsRegister(new LIsNull(value)); | |
| 1531 } | 1441 } |
| 1532 | 1442 |
| 1533 | 1443 |
| 1534 LInstruction* LChunkBuilder::DoIsObject(HIsObject* instr) { | 1444 LInstruction* LChunkBuilder::DoIsObjectAndBranch(HIsObjectAndBranch* instr) { |
| 1535 ASSERT(instr->value()->representation().IsTagged()); | 1445 ASSERT(instr->value()->representation().IsTagged()); |
| 1536 LOperand* value = UseRegisterAtStart(instr->value()); | 1446 LOperand* temp = TempRegister(); |
| 1537 | 1447 return new LIsObjectAndBranch(UseRegisterAtStart(instr->value()), temp); |
| 1538 return DefineAsRegister(new LIsObject(value)); | |
| 1539 } | 1448 } |
| 1540 | 1449 |
| 1541 | 1450 |
| 1542 LInstruction* LChunkBuilder::DoIsSmi(HIsSmi* instr) { | 1451 LInstruction* LChunkBuilder::DoIsSmiAndBranch(HIsSmiAndBranch* instr) { |
| 1543 ASSERT(instr->value()->representation().IsTagged()); | 1452 ASSERT(instr->value()->representation().IsTagged()); |
| 1544 LOperand* value = UseAtStart(instr->value()); | 1453 return new LIsSmiAndBranch(Use(instr->value())); |
| 1545 | |
| 1546 return DefineAsRegister(new LIsSmi(value)); | |
| 1547 } | 1454 } |
| 1548 | 1455 |
| 1549 | 1456 |
| 1550 LInstruction* LChunkBuilder::DoIsUndetectable(HIsUndetectable* instr) { | 1457 LInstruction* LChunkBuilder::DoIsUndetectableAndBranch( |
| 1458 HIsUndetectableAndBranch* instr) { |
| 1551 ASSERT(instr->value()->representation().IsTagged()); | 1459 ASSERT(instr->value()->representation().IsTagged()); |
| 1552 LOperand* value = UseRegisterAtStart(instr->value()); | 1460 return new LIsUndetectableAndBranch(UseRegisterAtStart(instr->value()), |
| 1553 | 1461 TempRegister()); |
| 1554 return DefineAsRegister(new LIsUndetectable(value)); | |
| 1555 } | 1462 } |
| 1556 | 1463 |
| 1557 | 1464 |
| 1558 LInstruction* LChunkBuilder::DoHasInstanceType(HHasInstanceType* instr) { | 1465 LInstruction* LChunkBuilder::DoHasInstanceTypeAndBranch( |
| 1466 HHasInstanceTypeAndBranch* instr) { |
| 1559 ASSERT(instr->value()->representation().IsTagged()); | 1467 ASSERT(instr->value()->representation().IsTagged()); |
| 1560 LOperand* value = UseRegisterAtStart(instr->value()); | 1468 return new LHasInstanceTypeAndBranch(UseRegisterAtStart(instr->value())); |
| 1561 | |
| 1562 return DefineAsRegister(new LHasInstanceType(value)); | |
| 1563 } | 1469 } |
| 1564 | 1470 |
| 1565 | 1471 |
| 1566 LInstruction* LChunkBuilder::DoGetCachedArrayIndex( | 1472 LInstruction* LChunkBuilder::DoGetCachedArrayIndex( |
| 1567 HGetCachedArrayIndex* instr) { | 1473 HGetCachedArrayIndex* instr) { |
| 1568 ASSERT(instr->value()->representation().IsTagged()); | 1474 ASSERT(instr->value()->representation().IsTagged()); |
| 1569 LOperand* value = UseRegisterAtStart(instr->value()); | 1475 LOperand* value = UseRegisterAtStart(instr->value()); |
| 1570 | 1476 |
| 1571 return DefineAsRegister(new LGetCachedArrayIndex(value)); | 1477 return DefineAsRegister(new LGetCachedArrayIndex(value)); |
| 1572 } | 1478 } |
| 1573 | 1479 |
| 1574 | 1480 |
| 1575 LInstruction* LChunkBuilder::DoHasCachedArrayIndex( | 1481 LInstruction* LChunkBuilder::DoHasCachedArrayIndexAndBranch( |
| 1576 HHasCachedArrayIndex* instr) { | 1482 HHasCachedArrayIndexAndBranch* instr) { |
| 1577 ASSERT(instr->value()->representation().IsTagged()); | 1483 ASSERT(instr->value()->representation().IsTagged()); |
| 1578 LOperand* value = UseRegister(instr->value()); | 1484 return new LHasCachedArrayIndexAndBranch( |
| 1579 | 1485 UseRegisterAtStart(instr->value())); |
| 1580 return DefineAsRegister(new LHasCachedArrayIndex(value)); | |
| 1581 } | 1486 } |
| 1582 | 1487 |
| 1583 | 1488 |
| 1584 LInstruction* LChunkBuilder::DoClassOfTest(HClassOfTest* instr) { | 1489 LInstruction* LChunkBuilder::DoClassOfTestAndBranch( |
| 1490 HClassOfTestAndBranch* instr) { |
| 1585 ASSERT(instr->value()->representation().IsTagged()); | 1491 ASSERT(instr->value()->representation().IsTagged()); |
| 1586 LOperand* value = UseTempRegister(instr->value()); | 1492 return new LClassOfTestAndBranch(UseTempRegister(instr->value()), |
| 1587 return DefineSameAsFirst(new LClassOfTest(value)); | 1493 TempRegister()); |
| 1588 } | 1494 } |
| 1589 | 1495 |
| 1590 | 1496 |
| 1591 LInstruction* LChunkBuilder::DoJSArrayLength(HJSArrayLength* instr) { | 1497 LInstruction* LChunkBuilder::DoJSArrayLength(HJSArrayLength* instr) { |
| 1592 LOperand* array = UseRegisterAtStart(instr->value()); | 1498 LOperand* array = UseRegisterAtStart(instr->value()); |
| 1593 return DefineAsRegister(new LJSArrayLength(array)); | 1499 return DefineAsRegister(new LJSArrayLength(array)); |
| 1594 } | 1500 } |
| 1595 | 1501 |
| 1596 | 1502 |
| 1597 LInstruction* LChunkBuilder::DoExternalArrayLength( | 1503 LInstruction* LChunkBuilder::DoExternalArrayLength( |
| 1598 HExternalArrayLength* instr) { | 1504 HExternalArrayLength* instr) { |
| 1599 LOperand* array = UseRegisterAtStart(instr->value()); | 1505 LOperand* array = UseRegisterAtStart(instr->value()); |
| 1600 return DefineAsRegister(new LExternalArrayLength(array)); | 1506 return DefineAsRegister(new LExternalArrayLength(array)); |
| 1601 } | 1507 } |
| 1602 | 1508 |
| 1603 | 1509 |
| 1604 LInstruction* LChunkBuilder::DoFixedArrayLength(HFixedArrayLength* instr) { | 1510 LInstruction* LChunkBuilder::DoFixedArrayLength(HFixedArrayLength* instr) { |
| 1605 LOperand* array = UseRegisterAtStart(instr->value()); | 1511 LOperand* array = UseRegisterAtStart(instr->value()); |
| 1606 return DefineAsRegister(new LFixedArrayLength(array)); | 1512 return DefineAsRegister(new LFixedArrayLength(array)); |
| 1607 } | 1513 } |
| 1608 | 1514 |
| 1609 | 1515 |
| 1516 LInstruction* LChunkBuilder::DoElementsKind(HElementsKind* instr) { |
| 1517 LOperand* object = UseRegisterAtStart(instr->value()); |
| 1518 return DefineAsRegister(new LElementsKind(object)); |
| 1519 } |
| 1520 |
| 1521 |
| 1610 LInstruction* LChunkBuilder::DoValueOf(HValueOf* instr) { | 1522 LInstruction* LChunkBuilder::DoValueOf(HValueOf* instr) { |
| 1611 LOperand* object = UseRegister(instr->value()); | 1523 LOperand* object = UseRegister(instr->value()); |
| 1612 LValueOf* result = new LValueOf(object, TempRegister()); | 1524 LValueOf* result = new LValueOf(object, TempRegister()); |
| 1613 return AssignEnvironment(DefineSameAsFirst(result)); | 1525 return AssignEnvironment(DefineAsRegister(result)); |
| 1614 } | 1526 } |
| 1615 | 1527 |
| 1616 | 1528 |
| 1617 LInstruction* LChunkBuilder::DoBoundsCheck(HBoundsCheck* instr) { | 1529 LInstruction* LChunkBuilder::DoBoundsCheck(HBoundsCheck* instr) { |
| 1618 return AssignEnvironment(new LBoundsCheck(UseRegisterAtStart(instr->index()), | 1530 return AssignEnvironment(new LBoundsCheck(UseRegisterAtStart(instr->index()), |
| 1619 UseRegister(instr->length()))); | 1531 UseRegister(instr->length()))); |
| 1620 } | 1532 } |
| 1621 | 1533 |
| 1622 | 1534 |
| 1623 LInstruction* LChunkBuilder::DoAbnormalExit(HAbnormalExit* instr) { | 1535 LInstruction* LChunkBuilder::DoAbnormalExit(HAbnormalExit* instr) { |
| 1624 // The control instruction marking the end of a block that completed | 1536 // The control instruction marking the end of a block that completed |
| 1625 // abruptly (e.g., threw an exception). There is nothing specific to do. | 1537 // abruptly (e.g., threw an exception). There is nothing specific to do. |
| 1626 return NULL; | 1538 return NULL; |
| 1627 } | 1539 } |
| 1628 | 1540 |
| 1629 | 1541 |
| 1630 LInstruction* LChunkBuilder::DoThrow(HThrow* instr) { | 1542 LInstruction* LChunkBuilder::DoThrow(HThrow* instr) { |
| 1631 LOperand* value = UseFixed(instr->value(), r0); | 1543 LOperand* value = UseFixed(instr->value(), r0); |
| 1632 return MarkAsCall(new LThrow(value), instr); | 1544 return MarkAsCall(new LThrow(value), instr); |
| 1633 } | 1545 } |
| 1634 | 1546 |
| 1635 | 1547 |
| 1548 LInstruction* LChunkBuilder::DoUseConst(HUseConst* instr) { |
| 1549 return NULL; |
| 1550 } |
| 1551 |
| 1552 |
| 1636 LInstruction* LChunkBuilder::DoForceRepresentation(HForceRepresentation* bad) { | 1553 LInstruction* LChunkBuilder::DoForceRepresentation(HForceRepresentation* bad) { |
| 1637 // All HForceRepresentation instructions should be eliminated in the | 1554 // All HForceRepresentation instructions should be eliminated in the |
| 1638 // representation change phase of Hydrogen. | 1555 // representation change phase of Hydrogen. |
| 1639 UNREACHABLE(); | 1556 UNREACHABLE(); |
| 1640 return NULL; | 1557 return NULL; |
| 1641 } | 1558 } |
| 1642 | 1559 |
| 1643 | 1560 |
| 1644 LInstruction* LChunkBuilder::DoChange(HChange* instr) { | 1561 LInstruction* LChunkBuilder::DoChange(HChange* instr) { |
| 1645 Representation from = instr->from(); | 1562 Representation from = instr->from(); |
| 1646 Representation to = instr->to(); | 1563 Representation to = instr->to(); |
| 1647 if (from.IsTagged()) { | 1564 if (from.IsTagged()) { |
| 1648 if (to.IsDouble()) { | 1565 if (to.IsDouble()) { |
| 1649 LOperand* value = UseRegister(instr->value()); | 1566 LOperand* value = UseRegister(instr->value()); |
| 1650 LNumberUntagD* res = new LNumberUntagD(value); | 1567 LNumberUntagD* res = new LNumberUntagD(value); |
| 1651 return AssignEnvironment(DefineAsRegister(res)); | 1568 return AssignEnvironment(DefineAsRegister(res)); |
| 1652 } else { | 1569 } else { |
| 1653 ASSERT(to.IsInteger32()); | 1570 ASSERT(to.IsInteger32()); |
| 1654 LOperand* value = UseRegister(instr->value()); | 1571 LOperand* value = UseRegister(instr->value()); |
| 1655 bool needs_check = !instr->value()->type().IsSmi(); | 1572 bool needs_check = !instr->value()->type().IsSmi(); |
| 1656 LInstruction* res = NULL; | 1573 LInstruction* res = NULL; |
| 1657 if (!needs_check) { | 1574 if (!needs_check) { |
| 1658 res = DefineSameAsFirst(new LSmiUntag(value, needs_check)); | 1575 res = DefineSameAsFirst(new LSmiUntag(value, needs_check)); |
| 1659 } else { | 1576 } else { |
| 1660 LOperand* temp1 = TempRegister(); | 1577 LOperand* temp1 = TempRegister(); |
| 1661 LOperand* temp2 = instr->CanTruncateToInt32() ? TempRegister() | 1578 LOperand* temp2 = instr->CanTruncateToInt32() ? TempRegister() |
| 1662 : NULL; | 1579 : NULL; |
| 1663 LOperand* temp3 = instr->CanTruncateToInt32() ? FixedTemp(d3) | 1580 LOperand* temp3 = instr->CanTruncateToInt32() ? FixedTemp(d11) |
| 1664 : NULL; | 1581 : NULL; |
| 1665 res = DefineSameAsFirst(new LTaggedToI(value, temp1, temp2, temp3)); | 1582 res = DefineSameAsFirst(new LTaggedToI(value, temp1, temp2, temp3)); |
| 1666 res = AssignEnvironment(res); | 1583 res = AssignEnvironment(res); |
| 1667 } | 1584 } |
| 1668 return res; | 1585 return res; |
| 1669 } | 1586 } |
| 1670 } else if (from.IsDouble()) { | 1587 } else if (from.IsDouble()) { |
| 1671 if (to.IsTagged()) { | 1588 if (to.IsTagged()) { |
| 1672 LOperand* value = UseRegister(instr->value()); | 1589 LOperand* value = UseRegister(instr->value()); |
| 1673 LOperand* temp1 = TempRegister(); | 1590 LOperand* temp1 = TempRegister(); |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1747 LInstruction* result = new LCheckMap(value); | 1664 LInstruction* result = new LCheckMap(value); |
| 1748 return AssignEnvironment(result); | 1665 return AssignEnvironment(result); |
| 1749 } | 1666 } |
| 1750 | 1667 |
| 1751 | 1668 |
| 1752 LInstruction* LChunkBuilder::DoClampToUint8(HClampToUint8* instr) { | 1669 LInstruction* LChunkBuilder::DoClampToUint8(HClampToUint8* instr) { |
| 1753 HValue* value = instr->value(); | 1670 HValue* value = instr->value(); |
| 1754 Representation input_rep = value->representation(); | 1671 Representation input_rep = value->representation(); |
| 1755 LOperand* reg = UseRegister(value); | 1672 LOperand* reg = UseRegister(value); |
| 1756 if (input_rep.IsDouble()) { | 1673 if (input_rep.IsDouble()) { |
| 1757 return DefineAsRegister(new LClampDToUint8(reg, FixedTemp(d1))); | 1674 return DefineAsRegister(new LClampDToUint8(reg, FixedTemp(d11))); |
| 1758 } else if (input_rep.IsInteger32()) { | 1675 } else if (input_rep.IsInteger32()) { |
| 1759 return DefineAsRegister(new LClampIToUint8(reg)); | 1676 return DefineAsRegister(new LClampIToUint8(reg)); |
| 1760 } else { | 1677 } else { |
| 1761 ASSERT(input_rep.IsTagged()); | 1678 ASSERT(input_rep.IsTagged()); |
| 1762 // Register allocator doesn't (yet) support allocation of double | 1679 // Register allocator doesn't (yet) support allocation of double |
| 1763 // temps. Reserve d1 explicitly. | 1680 // temps. Reserve d1 explicitly. |
| 1764 LClampTToUint8* result = new LClampTToUint8(reg, FixedTemp(d1)); | 1681 LClampTToUint8* result = new LClampTToUint8(reg, FixedTemp(d11)); |
| 1765 return AssignEnvironment(DefineAsRegister(result)); | 1682 return AssignEnvironment(DefineAsRegister(result)); |
| 1766 } | 1683 } |
| 1767 } | 1684 } |
| 1768 | 1685 |
| 1769 | 1686 |
| 1687 LInstruction* LChunkBuilder::DoToInt32(HToInt32* instr) { |
| 1688 HValue* value = instr->value(); |
| 1689 Representation input_rep = value->representation(); |
| 1690 LOperand* reg = UseRegister(value); |
| 1691 if (input_rep.IsDouble()) { |
| 1692 LOperand* temp1 = TempRegister(); |
| 1693 LOperand* temp2 = TempRegister(); |
| 1694 LDoubleToI* res = new LDoubleToI(reg, temp1, temp2); |
| 1695 return AssignEnvironment(DefineAsRegister(res)); |
| 1696 } else if (input_rep.IsInteger32()) { |
| 1697 // Canonicalization should already have removed the hydrogen instruction in |
| 1698 // this case, since it is a noop. |
| 1699 UNREACHABLE(); |
| 1700 return NULL; |
| 1701 } else { |
| 1702 ASSERT(input_rep.IsTagged()); |
| 1703 LOperand* temp1 = TempRegister(); |
| 1704 LOperand* temp2 = TempRegister(); |
| 1705 LOperand* temp3 = FixedTemp(d11); |
| 1706 LTaggedToI* res = new LTaggedToI(reg, temp1, temp2, temp3); |
| 1707 return AssignEnvironment(DefineSameAsFirst(res)); |
| 1708 } |
| 1709 } |
| 1710 |
| 1711 |
| 1770 LInstruction* LChunkBuilder::DoReturn(HReturn* instr) { | 1712 LInstruction* LChunkBuilder::DoReturn(HReturn* instr) { |
| 1771 return new LReturn(UseFixed(instr->value(), r0)); | 1713 return new LReturn(UseFixed(instr->value(), r0)); |
| 1772 } | 1714 } |
| 1773 | 1715 |
| 1774 | 1716 |
| 1775 LInstruction* LChunkBuilder::DoConstant(HConstant* instr) { | 1717 LInstruction* LChunkBuilder::DoConstant(HConstant* instr) { |
| 1776 Representation r = instr->representation(); | 1718 Representation r = instr->representation(); |
| 1777 if (r.IsInteger32()) { | 1719 if (r.IsInteger32()) { |
| 1778 return DefineAsRegister(new LConstantI); | 1720 return DefineAsRegister(new LConstantI); |
| 1779 } else if (r.IsDouble()) { | 1721 } else if (r.IsDouble()) { |
| (...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1891 } | 1833 } |
| 1892 | 1834 |
| 1893 | 1835 |
| 1894 LInstruction* LChunkBuilder::DoLoadKeyedFastElement( | 1836 LInstruction* LChunkBuilder::DoLoadKeyedFastElement( |
| 1895 HLoadKeyedFastElement* instr) { | 1837 HLoadKeyedFastElement* instr) { |
| 1896 ASSERT(instr->representation().IsTagged()); | 1838 ASSERT(instr->representation().IsTagged()); |
| 1897 ASSERT(instr->key()->representation().IsInteger32()); | 1839 ASSERT(instr->key()->representation().IsInteger32()); |
| 1898 LOperand* obj = UseRegisterAtStart(instr->object()); | 1840 LOperand* obj = UseRegisterAtStart(instr->object()); |
| 1899 LOperand* key = UseRegisterAtStart(instr->key()); | 1841 LOperand* key = UseRegisterAtStart(instr->key()); |
| 1900 LLoadKeyedFastElement* result = new LLoadKeyedFastElement(obj, key); | 1842 LLoadKeyedFastElement* result = new LLoadKeyedFastElement(obj, key); |
| 1901 return AssignEnvironment(DefineSameAsFirst(result)); | 1843 return AssignEnvironment(DefineAsRegister(result)); |
| 1902 } | 1844 } |
| 1903 | 1845 |
| 1904 | 1846 |
| 1905 LInstruction* LChunkBuilder::DoLoadKeyedSpecializedArrayElement( | 1847 LInstruction* LChunkBuilder::DoLoadKeyedSpecializedArrayElement( |
| 1906 HLoadKeyedSpecializedArrayElement* instr) { | 1848 HLoadKeyedSpecializedArrayElement* instr) { |
| 1907 ExternalArrayType array_type = instr->array_type(); | 1849 JSObject::ElementsKind elements_kind = instr->elements_kind(); |
| 1908 Representation representation(instr->representation()); | 1850 Representation representation(instr->representation()); |
| 1909 ASSERT( | 1851 ASSERT( |
| 1910 (representation.IsInteger32() && (array_type != kExternalFloatArray && | 1852 (representation.IsInteger32() && |
| 1911 array_type != kExternalDoubleArray)) || | 1853 (elements_kind != JSObject::EXTERNAL_FLOAT_ELEMENTS) && |
| 1912 (representation.IsDouble() && (array_type == kExternalFloatArray || | 1854 (elements_kind != JSObject::EXTERNAL_DOUBLE_ELEMENTS)) || |
| 1913 array_type == kExternalDoubleArray))); | 1855 (representation.IsDouble() && |
| 1856 ((elements_kind == JSObject::EXTERNAL_FLOAT_ELEMENTS) || |
| 1857 (elements_kind == JSObject::EXTERNAL_DOUBLE_ELEMENTS)))); |
| 1914 ASSERT(instr->key()->representation().IsInteger32()); | 1858 ASSERT(instr->key()->representation().IsInteger32()); |
| 1915 LOperand* external_pointer = UseRegister(instr->external_pointer()); | 1859 LOperand* external_pointer = UseRegister(instr->external_pointer()); |
| 1916 LOperand* key = UseRegisterOrConstant(instr->key()); | 1860 LOperand* key = UseRegisterOrConstant(instr->key()); |
| 1917 LLoadKeyedSpecializedArrayElement* result = | 1861 LLoadKeyedSpecializedArrayElement* result = |
| 1918 new LLoadKeyedSpecializedArrayElement(external_pointer, key); | 1862 new LLoadKeyedSpecializedArrayElement(external_pointer, key); |
| 1919 LInstruction* load_instr = DefineAsRegister(result); | 1863 LInstruction* load_instr = DefineAsRegister(result); |
| 1920 // An unsigned int array load might overflow and cause a deopt, make sure it | 1864 // An unsigned int array load might overflow and cause a deopt, make sure it |
| 1921 // has an environment. | 1865 // has an environment. |
| 1922 return (array_type == kExternalUnsignedIntArray) ? | 1866 return (elements_kind == JSObject::EXTERNAL_UNSIGNED_INT_ELEMENTS) ? |
| 1923 AssignEnvironment(load_instr) : load_instr; | 1867 AssignEnvironment(load_instr) : load_instr; |
| 1924 } | 1868 } |
| 1925 | 1869 |
| 1926 | 1870 |
| 1927 LInstruction* LChunkBuilder::DoLoadKeyedGeneric(HLoadKeyedGeneric* instr) { | 1871 LInstruction* LChunkBuilder::DoLoadKeyedGeneric(HLoadKeyedGeneric* instr) { |
| 1928 LOperand* object = UseFixed(instr->object(), r1); | 1872 LOperand* object = UseFixed(instr->object(), r1); |
| 1929 LOperand* key = UseFixed(instr->key(), r0); | 1873 LOperand* key = UseFixed(instr->key(), r0); |
| 1930 | 1874 |
| 1931 LInstruction* result = | 1875 LInstruction* result = |
| 1932 DefineFixed(new LLoadKeyedGeneric(object, key), r0); | 1876 DefineFixed(new LLoadKeyedGeneric(object, key), r0); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 1949 ? UseTempRegister(instr->key()) | 1893 ? UseTempRegister(instr->key()) |
| 1950 : UseRegisterOrConstantAtStart(instr->key()); | 1894 : UseRegisterOrConstantAtStart(instr->key()); |
| 1951 | 1895 |
| 1952 return AssignEnvironment(new LStoreKeyedFastElement(obj, key, val)); | 1896 return AssignEnvironment(new LStoreKeyedFastElement(obj, key, val)); |
| 1953 } | 1897 } |
| 1954 | 1898 |
| 1955 | 1899 |
| 1956 LInstruction* LChunkBuilder::DoStoreKeyedSpecializedArrayElement( | 1900 LInstruction* LChunkBuilder::DoStoreKeyedSpecializedArrayElement( |
| 1957 HStoreKeyedSpecializedArrayElement* instr) { | 1901 HStoreKeyedSpecializedArrayElement* instr) { |
| 1958 Representation representation(instr->value()->representation()); | 1902 Representation representation(instr->value()->representation()); |
| 1959 ExternalArrayType array_type = instr->array_type(); | 1903 JSObject::ElementsKind elements_kind = instr->elements_kind(); |
| 1960 ASSERT( | 1904 ASSERT( |
| 1961 (representation.IsInteger32() && (array_type != kExternalFloatArray && | 1905 (representation.IsInteger32() && |
| 1962 array_type != kExternalDoubleArray)) || | 1906 (elements_kind != JSObject::EXTERNAL_FLOAT_ELEMENTS) && |
| 1963 (representation.IsDouble() && (array_type == kExternalFloatArray || | 1907 (elements_kind != JSObject::EXTERNAL_DOUBLE_ELEMENTS)) || |
| 1964 array_type == kExternalDoubleArray))); | 1908 (representation.IsDouble() && |
| 1909 ((elements_kind == JSObject::EXTERNAL_FLOAT_ELEMENTS) || |
| 1910 (elements_kind == JSObject::EXTERNAL_DOUBLE_ELEMENTS)))); |
| 1965 ASSERT(instr->external_pointer()->representation().IsExternal()); | 1911 ASSERT(instr->external_pointer()->representation().IsExternal()); |
| 1966 ASSERT(instr->key()->representation().IsInteger32()); | 1912 ASSERT(instr->key()->representation().IsInteger32()); |
| 1967 | 1913 |
| 1968 LOperand* external_pointer = UseRegister(instr->external_pointer()); | 1914 LOperand* external_pointer = UseRegister(instr->external_pointer()); |
| 1969 bool val_is_temp_register = array_type == kExternalPixelArray || | 1915 bool val_is_temp_register = |
| 1970 array_type == kExternalFloatArray; | 1916 elements_kind == JSObject::EXTERNAL_PIXEL_ELEMENTS || |
| 1917 elements_kind == JSObject::EXTERNAL_FLOAT_ELEMENTS; |
| 1971 LOperand* val = val_is_temp_register | 1918 LOperand* val = val_is_temp_register |
| 1972 ? UseTempRegister(instr->value()) | 1919 ? UseTempRegister(instr->value()) |
| 1973 : UseRegister(instr->value()); | 1920 : UseRegister(instr->value()); |
| 1974 LOperand* key = UseRegisterOrConstant(instr->key()); | 1921 LOperand* key = UseRegisterOrConstant(instr->key()); |
| 1975 | 1922 |
| 1976 return new LStoreKeyedSpecializedArrayElement(external_pointer, | 1923 return new LStoreKeyedSpecializedArrayElement(external_pointer, |
| 1977 key, | 1924 key, |
| 1978 val); | 1925 val); |
| 1979 } | 1926 } |
| 1980 | 1927 |
| (...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2080 | 2027 |
| 2081 | 2028 |
| 2082 LInstruction* LChunkBuilder::DoParameter(HParameter* instr) { | 2029 LInstruction* LChunkBuilder::DoParameter(HParameter* instr) { |
| 2083 int spill_index = chunk()->GetParameterStackSlot(instr->index()); | 2030 int spill_index = chunk()->GetParameterStackSlot(instr->index()); |
| 2084 return DefineAsSpilled(new LParameter, spill_index); | 2031 return DefineAsSpilled(new LParameter, spill_index); |
| 2085 } | 2032 } |
| 2086 | 2033 |
| 2087 | 2034 |
| 2088 LInstruction* LChunkBuilder::DoUnknownOSRValue(HUnknownOSRValue* instr) { | 2035 LInstruction* LChunkBuilder::DoUnknownOSRValue(HUnknownOSRValue* instr) { |
| 2089 int spill_index = chunk()->GetNextSpillIndex(false); // Not double-width. | 2036 int spill_index = chunk()->GetNextSpillIndex(false); // Not double-width. |
| 2037 if (spill_index > LUnallocated::kMaxFixedIndex) { |
| 2038 Abort("Too many spill slots needed for OSR"); |
| 2039 spill_index = 0; |
| 2040 } |
| 2090 return DefineAsSpilled(new LUnknownOSRValue, spill_index); | 2041 return DefineAsSpilled(new LUnknownOSRValue, spill_index); |
| 2091 } | 2042 } |
| 2092 | 2043 |
| 2093 | 2044 |
| 2094 LInstruction* LChunkBuilder::DoCallStub(HCallStub* instr) { | 2045 LInstruction* LChunkBuilder::DoCallStub(HCallStub* instr) { |
| 2095 argument_count_ -= instr->argument_count(); | 2046 argument_count_ -= instr->argument_count(); |
| 2096 return MarkAsCall(DefineFixed(new LCallStub, r0), instr); | 2047 return MarkAsCall(DefineFixed(new LCallStub, r0), instr); |
| 2097 } | 2048 } |
| 2098 | 2049 |
| 2099 | 2050 |
| (...skipping 21 matching lines...) Expand all Loading... |
| 2121 return MarkAsCall(DefineFixed(result, r0), instr); | 2072 return MarkAsCall(DefineFixed(result, r0), instr); |
| 2122 } | 2073 } |
| 2123 | 2074 |
| 2124 | 2075 |
| 2125 LInstruction* LChunkBuilder::DoTypeof(HTypeof* instr) { | 2076 LInstruction* LChunkBuilder::DoTypeof(HTypeof* instr) { |
| 2126 LTypeof* result = new LTypeof(UseFixed(instr->value(), r0)); | 2077 LTypeof* result = new LTypeof(UseFixed(instr->value(), r0)); |
| 2127 return MarkAsCall(DefineFixed(result, r0), instr); | 2078 return MarkAsCall(DefineFixed(result, r0), instr); |
| 2128 } | 2079 } |
| 2129 | 2080 |
| 2130 | 2081 |
| 2131 LInstruction* LChunkBuilder::DoTypeofIs(HTypeofIs* instr) { | 2082 LInstruction* LChunkBuilder::DoTypeofIsAndBranch(HTypeofIsAndBranch* instr) { |
| 2132 return DefineSameAsFirst(new LTypeofIs(UseRegister(instr->value()))); | 2083 return new LTypeofIsAndBranch(UseTempRegister(instr->value())); |
| 2133 } | 2084 } |
| 2134 | 2085 |
| 2135 | 2086 |
| 2136 LInstruction* LChunkBuilder::DoIsConstructCall(HIsConstructCall* instr) { | 2087 LInstruction* LChunkBuilder::DoIsConstructCallAndBranch( |
| 2137 return DefineAsRegister(new LIsConstructCall()); | 2088 HIsConstructCallAndBranch* instr) { |
| 2089 return new LIsConstructCallAndBranch(TempRegister()); |
| 2138 } | 2090 } |
| 2139 | 2091 |
| 2140 | 2092 |
| 2141 LInstruction* LChunkBuilder::DoSimulate(HSimulate* instr) { | 2093 LInstruction* LChunkBuilder::DoSimulate(HSimulate* instr) { |
| 2142 HEnvironment* env = current_block_->last_environment(); | 2094 HEnvironment* env = current_block_->last_environment(); |
| 2143 ASSERT(env != NULL); | 2095 ASSERT(env != NULL); |
| 2144 | 2096 |
| 2145 env->set_ast_id(instr->ast_id()); | 2097 env->set_ast_id(instr->ast_id()); |
| 2146 | 2098 |
| 2147 env->Drop(instr->pop_count()); | 2099 env->Drop(instr->pop_count()); |
| (...skipping 15 matching lines...) Expand all Loading... |
| 2163 set_deoptimization_environment(result->environment()); | 2115 set_deoptimization_environment(result->environment()); |
| 2164 ClearInstructionPendingDeoptimizationEnvironment(); | 2116 ClearInstructionPendingDeoptimizationEnvironment(); |
| 2165 return result; | 2117 return result; |
| 2166 } | 2118 } |
| 2167 | 2119 |
| 2168 return NULL; | 2120 return NULL; |
| 2169 } | 2121 } |
| 2170 | 2122 |
| 2171 | 2123 |
| 2172 LInstruction* LChunkBuilder::DoStackCheck(HStackCheck* instr) { | 2124 LInstruction* LChunkBuilder::DoStackCheck(HStackCheck* instr) { |
| 2173 return MarkAsCall(new LStackCheck, instr); | 2125 if (instr->is_function_entry()) { |
| 2126 return MarkAsCall(new LStackCheck, instr); |
| 2127 } else { |
| 2128 ASSERT(instr->is_backwards_branch()); |
| 2129 return AssignEnvironment(AssignPointerMap(new LStackCheck)); |
| 2130 } |
| 2174 } | 2131 } |
| 2175 | 2132 |
| 2176 | 2133 |
| 2177 LInstruction* LChunkBuilder::DoEnterInlined(HEnterInlined* instr) { | 2134 LInstruction* LChunkBuilder::DoEnterInlined(HEnterInlined* instr) { |
| 2178 HEnvironment* outer = current_block_->last_environment(); | 2135 HEnvironment* outer = current_block_->last_environment(); |
| 2179 HConstant* undefined = graph()->GetConstantUndefined(); | 2136 HConstant* undefined = graph()->GetConstantUndefined(); |
| 2180 HEnvironment* inner = outer->CopyForInlining(instr->closure(), | 2137 HEnvironment* inner = outer->CopyForInlining(instr->closure(), |
| 2181 instr->function(), | 2138 instr->function(), |
| 2182 HEnvironment::LITHIUM, | |
| 2183 undefined, | 2139 undefined, |
| 2184 instr->call_kind()); | 2140 instr->call_kind()); |
| 2185 current_block_->UpdateEnvironment(inner); | 2141 current_block_->UpdateEnvironment(inner); |
| 2186 chunk_->AddInlinedClosure(instr->closure()); | 2142 chunk_->AddInlinedClosure(instr->closure()); |
| 2187 return NULL; | 2143 return NULL; |
| 2188 } | 2144 } |
| 2189 | 2145 |
| 2190 | 2146 |
| 2191 LInstruction* LChunkBuilder::DoLeaveInlined(HLeaveInlined* instr) { | 2147 LInstruction* LChunkBuilder::DoLeaveInlined(HLeaveInlined* instr) { |
| 2192 HEnvironment* outer = current_block_->last_environment()->outer(); | 2148 HEnvironment* outer = current_block_->last_environment()->outer(); |
| 2193 current_block_->UpdateEnvironment(outer); | 2149 current_block_->UpdateEnvironment(outer); |
| 2194 return NULL; | 2150 return NULL; |
| 2195 } | 2151 } |
| 2196 | 2152 |
| 2197 | 2153 |
| 2198 LInstruction* LChunkBuilder::DoIn(HIn* instr) { | 2154 LInstruction* LChunkBuilder::DoIn(HIn* instr) { |
| 2199 LOperand* key = UseRegisterAtStart(instr->key()); | 2155 LOperand* key = UseRegisterAtStart(instr->key()); |
| 2200 LOperand* object = UseRegisterAtStart(instr->object()); | 2156 LOperand* object = UseRegisterAtStart(instr->object()); |
| 2201 LIn* result = new LIn(key, object); | 2157 LIn* result = new LIn(key, object); |
| 2202 return MarkAsCall(DefineFixed(result, r0), instr); | 2158 return MarkAsCall(DefineFixed(result, r0), instr); |
| 2203 } | 2159 } |
| 2204 | 2160 |
| 2205 | 2161 |
| 2206 } } // namespace v8::internal | 2162 } } // namespace v8::internal |
| OLD | NEW |