| 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 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 83 | 83 |
| 84 if (HasPointerMap()) { | 84 if (HasPointerMap()) { |
| 85 stream->Add(" "); | 85 stream->Add(" "); |
| 86 pointer_map()->PrintTo(stream); | 86 pointer_map()->PrintTo(stream); |
| 87 } | 87 } |
| 88 } | 88 } |
| 89 | 89 |
| 90 | 90 |
| 91 template<int R, int I, int T> | 91 template<int R, int I, int T> |
| 92 void LTemplateInstruction<R, I, T>::PrintDataTo(StringStream* stream) { | 92 void LTemplateInstruction<R, I, T>::PrintDataTo(StringStream* stream) { |
| 93 for (int i = 0; i < I; i++) { | 93 stream->Add("= "); |
| 94 stream->Add(i == 0 ? "= " : " "); | 94 inputs_.PrintOperandsTo(stream); |
| 95 inputs_.at(i)->PrintTo(stream); | |
| 96 } | |
| 97 } | 95 } |
| 98 | 96 |
| 99 | 97 |
| 100 template<int R, int I, int T> | 98 template<int R, int I, int T> |
| 101 void LTemplateInstruction<R, I, T>::PrintOutputOperandTo(StringStream* stream) { | 99 void LTemplateInstruction<R, I, T>::PrintOutputOperandTo(StringStream* stream) { |
| 102 if (this->HasResult()) { | 100 results_.PrintOperandsTo(stream); |
| 103 this->result()->PrintTo(stream); | 101 } |
| 104 stream->Add(" "); | 102 |
| 103 |
| 104 template<typename T, int N> |
| 105 void OperandContainer<T, N>::PrintOperandsTo(StringStream* stream) { |
| 106 for (int i = 0; i < N; i++) { |
| 107 if (i > 0) stream->Add(" "); |
| 108 elems_[i]->PrintTo(stream); |
| 105 } | 109 } |
| 106 } | 110 } |
| 107 | 111 |
| 108 | 112 |
| 109 void LLabel::PrintDataTo(StringStream* stream) { | 113 void LLabel::PrintDataTo(StringStream* stream) { |
| 110 LGap::PrintDataTo(stream); | 114 LGap::PrintDataTo(stream); |
| 111 LLabel* rep = replacement(); | 115 LLabel* rep = replacement(); |
| 112 if (rep != NULL) { | 116 if (rep != NULL) { |
| 113 stream->Add(" Dead block replaced with B%d", rep->block_id()); | 117 stream->Add(" Dead block replaced with B%d", rep->block_id()); |
| 114 } | 118 } |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 165 } | 169 } |
| 166 | 170 |
| 167 | 171 |
| 168 void LGoto::PrintDataTo(StringStream* stream) { | 172 void LGoto::PrintDataTo(StringStream* stream) { |
| 169 stream->Add("B%d", block_id()); | 173 stream->Add("B%d", block_id()); |
| 170 } | 174 } |
| 171 | 175 |
| 172 | 176 |
| 173 void LBranch::PrintDataTo(StringStream* stream) { | 177 void LBranch::PrintDataTo(StringStream* stream) { |
| 174 stream->Add("B%d | B%d on ", true_block_id(), false_block_id()); | 178 stream->Add("B%d | B%d on ", true_block_id(), false_block_id()); |
| 175 input()->PrintTo(stream); | 179 InputAt(0)->PrintTo(stream); |
| 176 } | 180 } |
| 177 | 181 |
| 178 | 182 |
| 179 void LCmpIDAndBranch::PrintDataTo(StringStream* stream) { | 183 void LCmpIDAndBranch::PrintDataTo(StringStream* stream) { |
| 180 stream->Add("if "); | 184 stream->Add("if "); |
| 181 left()->PrintTo(stream); | 185 InputAt(0)->PrintTo(stream); |
| 182 stream->Add(" %s ", Token::String(op())); | 186 stream->Add(" %s ", Token::String(op())); |
| 183 right()->PrintTo(stream); | 187 InputAt(1)->PrintTo(stream); |
| 184 stream->Add(" then B%d else B%d", true_block_id(), false_block_id()); | 188 stream->Add(" then B%d else B%d", true_block_id(), false_block_id()); |
| 185 } | 189 } |
| 186 | 190 |
| 187 | 191 |
| 188 void LIsNullAndBranch::PrintDataTo(StringStream* stream) { | 192 void LIsNullAndBranch::PrintDataTo(StringStream* stream) { |
| 189 stream->Add("if "); | 193 stream->Add("if "); |
| 190 input()->PrintTo(stream); | 194 InputAt(0)->PrintTo(stream); |
| 191 stream->Add(is_strict() ? " === null" : " == null"); | 195 stream->Add(is_strict() ? " === null" : " == null"); |
| 192 stream->Add(" then B%d else B%d", true_block_id(), false_block_id()); | 196 stream->Add(" then B%d else B%d", true_block_id(), false_block_id()); |
| 193 } | 197 } |
| 194 | 198 |
| 195 | 199 |
| 196 void LIsObjectAndBranch::PrintDataTo(StringStream* stream) { | 200 void LIsObjectAndBranch::PrintDataTo(StringStream* stream) { |
| 197 stream->Add("if is_object("); | 201 stream->Add("if is_object("); |
| 198 input()->PrintTo(stream); | 202 InputAt(0)->PrintTo(stream); |
| 199 stream->Add(") then B%d else B%d", true_block_id(), false_block_id()); | 203 stream->Add(") then B%d else B%d", true_block_id(), false_block_id()); |
| 200 } | 204 } |
| 201 | 205 |
| 202 | 206 |
| 203 void LIsSmiAndBranch::PrintDataTo(StringStream* stream) { | 207 void LIsSmiAndBranch::PrintDataTo(StringStream* stream) { |
| 204 stream->Add("if is_smi("); | 208 stream->Add("if is_smi("); |
| 205 input()->PrintTo(stream); | 209 InputAt(0)->PrintTo(stream); |
| 206 stream->Add(") then B%d else B%d", true_block_id(), false_block_id()); | 210 stream->Add(") then B%d else B%d", true_block_id(), false_block_id()); |
| 207 } | 211 } |
| 208 | 212 |
| 209 | 213 |
| 210 void LHasInstanceTypeAndBranch::PrintDataTo(StringStream* stream) { | 214 void LHasInstanceTypeAndBranch::PrintDataTo(StringStream* stream) { |
| 211 stream->Add("if has_instance_type("); | 215 stream->Add("if has_instance_type("); |
| 212 input()->PrintTo(stream); | 216 InputAt(0)->PrintTo(stream); |
| 213 stream->Add(") then B%d else B%d", true_block_id(), false_block_id()); | 217 stream->Add(") then B%d else B%d", true_block_id(), false_block_id()); |
| 214 } | 218 } |
| 215 | 219 |
| 216 | 220 |
| 217 void LHasCachedArrayIndexAndBranch::PrintDataTo(StringStream* stream) { | 221 void LHasCachedArrayIndexAndBranch::PrintDataTo(StringStream* stream) { |
| 218 stream->Add("if has_cached_array_index("); | 222 stream->Add("if has_cached_array_index("); |
| 219 input()->PrintTo(stream); | 223 InputAt(0)->PrintTo(stream); |
| 220 stream->Add(") then B%d else B%d", true_block_id(), false_block_id()); | 224 stream->Add(") then B%d else B%d", true_block_id(), false_block_id()); |
| 221 } | 225 } |
| 222 | 226 |
| 223 | 227 |
| 224 void LClassOfTestAndBranch::PrintDataTo(StringStream* stream) { | 228 void LClassOfTestAndBranch::PrintDataTo(StringStream* stream) { |
| 225 stream->Add("if class_of_test("); | 229 stream->Add("if class_of_test("); |
| 226 input()->PrintTo(stream); | 230 InputAt(0)->PrintTo(stream); |
| 227 stream->Add(", \"%o\") then B%d else B%d", | 231 stream->Add(", \"%o\") then B%d else B%d", |
| 228 *hydrogen()->class_name(), | 232 *hydrogen()->class_name(), |
| 229 true_block_id(), | 233 true_block_id(), |
| 230 false_block_id()); | 234 false_block_id()); |
| 231 } | 235 } |
| 232 | 236 |
| 233 | 237 |
| 234 void LTypeofIs::PrintDataTo(StringStream* stream) { | 238 void LTypeofIs::PrintDataTo(StringStream* stream) { |
| 235 input()->PrintTo(stream); | 239 InputAt(0)->PrintTo(stream); |
| 236 stream->Add(" == \"%s\"", *hydrogen()->type_literal()->ToCString()); | 240 stream->Add(" == \"%s\"", *hydrogen()->type_literal()->ToCString()); |
| 237 } | 241 } |
| 238 | 242 |
| 239 | 243 |
| 240 void LTypeofIsAndBranch::PrintDataTo(StringStream* stream) { | 244 void LTypeofIsAndBranch::PrintDataTo(StringStream* stream) { |
| 241 stream->Add("if typeof "); | 245 stream->Add("if typeof "); |
| 242 input()->PrintTo(stream); | 246 InputAt(0)->PrintTo(stream); |
| 243 stream->Add(" == \"%s\" then B%d else B%d", | 247 stream->Add(" == \"%s\" then B%d else B%d", |
| 244 *hydrogen()->type_literal()->ToCString(), | 248 *hydrogen()->type_literal()->ToCString(), |
| 245 true_block_id(), false_block_id()); | 249 true_block_id(), false_block_id()); |
| 246 } | 250 } |
| 247 | 251 |
| 248 | 252 |
| 249 void LCallConstantFunction::PrintDataTo(StringStream* stream) { | 253 void LCallConstantFunction::PrintDataTo(StringStream* stream) { |
| 250 stream->Add("#%d / ", arity()); | 254 stream->Add("#%d / ", arity()); |
| 251 } | 255 } |
| 252 | 256 |
| 253 | 257 |
| 254 void LUnaryMathOperation::PrintDataTo(StringStream* stream) { | 258 void LUnaryMathOperation::PrintDataTo(StringStream* stream) { |
| 255 stream->Add("/%s ", hydrogen()->OpName()); | 259 stream->Add("/%s ", hydrogen()->OpName()); |
| 256 input()->PrintTo(stream); | 260 InputAt(0)->PrintTo(stream); |
| 257 } | 261 } |
| 258 | 262 |
| 259 | 263 |
| 260 void LLoadContextSlot::PrintDataTo(StringStream* stream) { | 264 void LLoadContextSlot::PrintDataTo(StringStream* stream) { |
| 261 stream->Add("(%d, %d)", context_chain_length(), slot_index()); | 265 stream->Add("(%d, %d)", context_chain_length(), slot_index()); |
| 262 } | 266 } |
| 263 | 267 |
| 264 | 268 |
| 265 void LCallKeyed::PrintDataTo(StringStream* stream) { | 269 void LCallKeyed::PrintDataTo(StringStream* stream) { |
| 266 stream->Add("[ecx] #%d / ", arity()); | 270 stream->Add("[ecx] #%d / ", arity()); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 279 } | 283 } |
| 280 | 284 |
| 281 | 285 |
| 282 void LCallKnownGlobal::PrintDataTo(StringStream* stream) { | 286 void LCallKnownGlobal::PrintDataTo(StringStream* stream) { |
| 283 stream->Add("#%d / ", arity()); | 287 stream->Add("#%d / ", arity()); |
| 284 } | 288 } |
| 285 | 289 |
| 286 | 290 |
| 287 void LCallNew::PrintDataTo(StringStream* stream) { | 291 void LCallNew::PrintDataTo(StringStream* stream) { |
| 288 stream->Add("= "); | 292 stream->Add("= "); |
| 289 input()->PrintTo(stream); | 293 InputAt(0)->PrintTo(stream); |
| 290 stream->Add(" #%d / ", arity()); | 294 stream->Add(" #%d / ", arity()); |
| 291 } | 295 } |
| 292 | 296 |
| 293 | 297 |
| 294 void LClassOfTest::PrintDataTo(StringStream* stream) { | 298 void LClassOfTest::PrintDataTo(StringStream* stream) { |
| 295 stream->Add("= class_of_test("); | 299 stream->Add("= class_of_test("); |
| 296 input()->PrintTo(stream); | 300 InputAt(0)->PrintTo(stream); |
| 297 stream->Add(", \"%o\")", *hydrogen()->class_name()); | 301 stream->Add(", \"%o\")", *hydrogen()->class_name()); |
| 298 } | 302 } |
| 299 | 303 |
| 300 | 304 |
| 301 void LAccessArgumentsAt::PrintDataTo(StringStream* stream) { | 305 void LAccessArgumentsAt::PrintDataTo(StringStream* stream) { |
| 302 arguments()->PrintTo(stream); | 306 arguments()->PrintTo(stream); |
| 303 | 307 |
| 304 stream->Add(" length "); | 308 stream->Add(" length "); |
| 305 length()->PrintTo(stream); | 309 length()->PrintTo(stream); |
| 306 | 310 |
| 307 stream->Add(" index "); | 311 stream->Add(" index "); |
| 308 index()->PrintTo(stream); | 312 index()->PrintTo(stream); |
| 309 } | 313 } |
| 310 | 314 |
| 311 | 315 |
| 312 int LChunk::GetNextSpillIndex(bool is_double) { | 316 int LChunk::GetNextSpillIndex(bool is_double) { |
| 313 // Skip a slot if for a double-width slot. | 317 // Skip a slot if for a double-width slot. |
| 314 if (is_double) spill_slot_count_++; | 318 if (is_double) spill_slot_count_++; |
| 315 return spill_slot_count_++; | 319 return spill_slot_count_++; |
| 316 } | 320 } |
| 317 | 321 |
| 318 | 322 |
| 319 LOperand* LChunk::GetNextSpillSlot(bool is_double) { | 323 LOperand* LChunk::GetNextSpillSlot(bool is_double) { |
| 320 int index = GetNextSpillIndex(is_double); | 324 int index = GetNextSpillIndex(is_double); |
| 321 if (is_double) { | 325 if (is_double) { |
| 322 return LDoubleStackSlot::Create(index); | 326 return LDoubleStackSlot::Create(index); |
| 323 } else { | 327 } else { |
| 324 return LStackSlot::Create(index); | 328 return LStackSlot::Create(index); |
| 325 } | 329 } |
| 326 } | 330 } |
| 327 | 331 |
| 328 | 332 |
| 329 void LChunk::MarkEmptyBlocks() { | 333 void LChunk::MarkEmptyBlocks() { |
| (...skipping 233 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 563 } | 567 } |
| 564 | 568 |
| 565 | 569 |
| 566 LOperand* LChunkBuilder::UseRegisterOrConstantAtStart(HValue* value) { | 570 LOperand* LChunkBuilder::UseRegisterOrConstantAtStart(HValue* value) { |
| 567 return value->IsConstant() | 571 return value->IsConstant() |
| 568 ? chunk_->DefineConstantOperand(HConstant::cast(value)) | 572 ? chunk_->DefineConstantOperand(HConstant::cast(value)) |
| 569 : UseRegisterAtStart(value); | 573 : UseRegisterAtStart(value); |
| 570 } | 574 } |
| 571 | 575 |
| 572 | 576 |
| 577 LOperand* LChunkBuilder::UseAny(HValue* value) { |
| 578 return value->IsConstant() |
| 579 ? chunk_->DefineConstantOperand(HConstant::cast(value)) |
| 580 : Use(value, new LUnallocated(LUnallocated::ANY)); |
| 581 } |
| 582 |
| 583 |
| 573 LOperand* LChunkBuilder::Use(HValue* value, LUnallocated* operand) { | 584 LOperand* LChunkBuilder::Use(HValue* value, LUnallocated* operand) { |
| 574 if (value->EmitAtUses()) { | 585 if (value->EmitAtUses()) { |
| 575 HInstruction* instr = HInstruction::cast(value); | 586 HInstruction* instr = HInstruction::cast(value); |
| 576 VisitInstruction(instr); | 587 VisitInstruction(instr); |
| 577 } | 588 } |
| 578 allocator_->RecordUse(value, operand); | 589 allocator_->RecordUse(value, operand); |
| 579 return operand; | 590 return operand; |
| 580 } | 591 } |
| 581 | 592 |
| 582 | 593 |
| (...skipping 293 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 876 if (current->has_position()) position_ = current->position(); | 887 if (current->has_position()) position_ = current->position(); |
| 877 LInstruction* instr = current->CompileToLithium(this); | 888 LInstruction* instr = current->CompileToLithium(this); |
| 878 | 889 |
| 879 if (instr != NULL) { | 890 if (instr != NULL) { |
| 880 if (FLAG_stress_pointer_maps && !instr->HasPointerMap()) { | 891 if (FLAG_stress_pointer_maps && !instr->HasPointerMap()) { |
| 881 instr = AssignPointerMap(instr); | 892 instr = AssignPointerMap(instr); |
| 882 } | 893 } |
| 883 if (FLAG_stress_environments && !instr->HasEnvironment()) { | 894 if (FLAG_stress_environments && !instr->HasEnvironment()) { |
| 884 instr = AssignEnvironment(instr); | 895 instr = AssignEnvironment(instr); |
| 885 } | 896 } |
| 886 if (current->IsBranch()) { | 897 if (current->IsBranch() && !instr->IsGoto()) { |
| 887 instr->set_hydrogen_value(HBranch::cast(current)->value()); | 898 // TODO(fschneider): Handle branch instructions uniformly like |
| 899 // other instructions. This requires us to generate the right |
| 900 // branch instruction already at the HIR level. |
| 901 ASSERT(instr->IsControl()); |
| 902 HBranch* branch = HBranch::cast(current); |
| 903 instr->set_hydrogen_value(branch->value()); |
| 904 HBasicBlock* first = branch->FirstSuccessor(); |
| 905 HBasicBlock* second = branch->SecondSuccessor(); |
| 906 ASSERT(first != NULL && second != NULL); |
| 907 instr->SetBranchTargets(first->block_id(), second->block_id()); |
| 888 } else { | 908 } else { |
| 889 instr->set_hydrogen_value(current); | 909 instr->set_hydrogen_value(current); |
| 890 } | 910 } |
| 891 | 911 |
| 892 int index = chunk_->AddInstruction(instr, current_block_); | 912 int index = chunk_->AddInstruction(instr, current_block_); |
| 893 allocator_->SummarizeInstruction(index); | 913 allocator_->SummarizeInstruction(index); |
| 894 } else { | 914 } else { |
| 895 // This instruction should be omitted. | 915 // This instruction should be omitted. |
| 896 allocator_->OmitInstruction(); | 916 allocator_->OmitInstruction(); |
| 897 } | 917 } |
| (...skipping 16 matching lines...) Expand all Loading... |
| 914 outer); | 934 outer); |
| 915 int argument_index = 0; | 935 int argument_index = 0; |
| 916 for (int i = 0; i < value_count; ++i) { | 936 for (int i = 0; i < value_count; ++i) { |
| 917 HValue* value = hydrogen_env->values()->at(i); | 937 HValue* value = hydrogen_env->values()->at(i); |
| 918 LOperand* op = NULL; | 938 LOperand* op = NULL; |
| 919 if (value->IsArgumentsObject()) { | 939 if (value->IsArgumentsObject()) { |
| 920 op = NULL; | 940 op = NULL; |
| 921 } else if (value->IsPushArgument()) { | 941 } else if (value->IsPushArgument()) { |
| 922 op = new LArgument(argument_index++); | 942 op = new LArgument(argument_index++); |
| 923 } else { | 943 } else { |
| 924 op = UseOrConstant(value); | 944 op = UseAny(value); |
| 925 if (op->IsUnallocated()) { | |
| 926 LUnallocated* unalloc = LUnallocated::cast(op); | |
| 927 unalloc->set_policy(LUnallocated::ANY); | |
| 928 } | |
| 929 } | 945 } |
| 930 result->AddValue(op, value->representation()); | 946 result->AddValue(op, value->representation()); |
| 931 } | 947 } |
| 932 | 948 |
| 933 return result; | 949 return result; |
| 934 } | 950 } |
| 935 | 951 |
| 936 | 952 |
| 937 LInstruction* LChunkBuilder::DoGoto(HGoto* instr) { | 953 LInstruction* LChunkBuilder::DoGoto(HGoto* instr) { |
| 938 LGoto* result = new LGoto(instr->FirstSuccessor()->block_id(), | 954 LGoto* result = new LGoto(instr->FirstSuccessor()->block_id(), |
| 939 instr->include_stack_check()); | 955 instr->include_stack_check()); |
| 940 return (instr->include_stack_check()) | 956 return (instr->include_stack_check()) |
| 941 ? AssignPointerMap(result) | 957 ? AssignPointerMap(result) |
| 942 : result; | 958 : result; |
| 943 } | 959 } |
| 944 | 960 |
| 945 | 961 |
| 946 LInstruction* LChunkBuilder::DoBranch(HBranch* instr) { | 962 LInstruction* LChunkBuilder::DoBranch(HBranch* instr) { |
| 947 HValue* v = instr->value(); | 963 HValue* v = instr->value(); |
| 948 HBasicBlock* first = instr->FirstSuccessor(); | |
| 949 HBasicBlock* second = instr->SecondSuccessor(); | |
| 950 ASSERT(first != NULL && second != NULL); | |
| 951 int first_id = first->block_id(); | |
| 952 int second_id = second->block_id(); | |
| 953 | |
| 954 if (v->EmitAtUses()) { | 964 if (v->EmitAtUses()) { |
| 955 if (v->IsClassOfTest()) { | 965 if (v->IsClassOfTest()) { |
| 956 HClassOfTest* compare = HClassOfTest::cast(v); | 966 HClassOfTest* compare = HClassOfTest::cast(v); |
| 957 ASSERT(compare->value()->representation().IsTagged()); | 967 ASSERT(compare->value()->representation().IsTagged()); |
| 958 | 968 |
| 959 return new LClassOfTestAndBranch(UseTempRegister(compare->value()), | 969 return new LClassOfTestAndBranch(UseTempRegister(compare->value()), |
| 960 TempRegister(), | 970 TempRegister(), |
| 961 TempRegister(), | 971 TempRegister()); |
| 962 first_id, | |
| 963 second_id); | |
| 964 } else if (v->IsCompare()) { | 972 } else if (v->IsCompare()) { |
| 965 HCompare* compare = HCompare::cast(v); | 973 HCompare* compare = HCompare::cast(v); |
| 966 Token::Value op = compare->token(); | 974 Token::Value op = compare->token(); |
| 967 HValue* left = compare->left(); | 975 HValue* left = compare->left(); |
| 968 HValue* right = compare->right(); | 976 HValue* right = compare->right(); |
| 969 Representation r = compare->GetInputRepresentation(); | 977 Representation r = compare->GetInputRepresentation(); |
| 970 if (r.IsInteger32()) { | 978 if (r.IsInteger32()) { |
| 971 ASSERT(left->representation().IsInteger32()); | 979 ASSERT(left->representation().IsInteger32()); |
| 972 ASSERT(right->representation().IsInteger32()); | 980 ASSERT(right->representation().IsInteger32()); |
| 973 | 981 |
| 974 return new LCmpIDAndBranch(UseRegisterAtStart(left), | 982 return new LCmpIDAndBranch(UseRegisterAtStart(left), |
| 975 UseOrConstantAtStart(right), | 983 UseOrConstantAtStart(right)); |
| 976 first_id, | |
| 977 second_id); | |
| 978 } else if (r.IsDouble()) { | 984 } else if (r.IsDouble()) { |
| 979 ASSERT(left->representation().IsDouble()); | 985 ASSERT(left->representation().IsDouble()); |
| 980 ASSERT(right->representation().IsDouble()); | 986 ASSERT(right->representation().IsDouble()); |
| 981 | 987 |
| 982 return new LCmpIDAndBranch(UseRegisterAtStart(left), | 988 return new LCmpIDAndBranch(UseRegisterAtStart(left), |
| 983 UseRegisterAtStart(right), | 989 UseRegisterAtStart(right)); |
| 984 first_id, | |
| 985 second_id); | |
| 986 } else { | 990 } else { |
| 987 ASSERT(left->representation().IsTagged()); | 991 ASSERT(left->representation().IsTagged()); |
| 988 ASSERT(right->representation().IsTagged()); | 992 ASSERT(right->representation().IsTagged()); |
| 989 bool reversed = op == Token::GT || op == Token::LTE; | 993 bool reversed = op == Token::GT || op == Token::LTE; |
| 990 LOperand* left_operand = UseFixed(left, reversed ? eax : edx); | 994 LOperand* left_operand = UseFixed(left, reversed ? eax : edx); |
| 991 LOperand* right_operand = UseFixed(right, reversed ? edx : eax); | 995 LOperand* right_operand = UseFixed(right, reversed ? edx : eax); |
| 992 LCmpTAndBranch* result = new LCmpTAndBranch(left_operand, | 996 LCmpTAndBranch* result = new LCmpTAndBranch(left_operand, |
| 993 right_operand, | 997 right_operand); |
| 994 first_id, | |
| 995 second_id); | |
| 996 return MarkAsCall(result, instr); | 998 return MarkAsCall(result, instr); |
| 997 } | 999 } |
| 998 } else if (v->IsIsSmi()) { | 1000 } else if (v->IsIsSmi()) { |
| 999 HIsSmi* compare = HIsSmi::cast(v); | 1001 HIsSmi* compare = HIsSmi::cast(v); |
| 1000 ASSERT(compare->value()->representation().IsTagged()); | 1002 ASSERT(compare->value()->representation().IsTagged()); |
| 1001 | 1003 |
| 1002 return new LIsSmiAndBranch(Use(compare->value()), | 1004 return new LIsSmiAndBranch(Use(compare->value())); |
| 1003 first_id, | |
| 1004 second_id); | |
| 1005 } else if (v->IsHasInstanceType()) { | 1005 } else if (v->IsHasInstanceType()) { |
| 1006 HHasInstanceType* compare = HHasInstanceType::cast(v); | 1006 HHasInstanceType* compare = HHasInstanceType::cast(v); |
| 1007 ASSERT(compare->value()->representation().IsTagged()); | 1007 ASSERT(compare->value()->representation().IsTagged()); |
| 1008 | 1008 |
| 1009 return new LHasInstanceTypeAndBranch(UseRegisterAtStart(compare->value()), | 1009 return new LHasInstanceTypeAndBranch(UseRegisterAtStart(compare->value()), |
| 1010 TempRegister(), | 1010 TempRegister()); |
| 1011 first_id, | |
| 1012 second_id); | |
| 1013 } else if (v->IsHasCachedArrayIndex()) { | 1011 } else if (v->IsHasCachedArrayIndex()) { |
| 1014 HHasCachedArrayIndex* compare = HHasCachedArrayIndex::cast(v); | 1012 HHasCachedArrayIndex* compare = HHasCachedArrayIndex::cast(v); |
| 1015 ASSERT(compare->value()->representation().IsTagged()); | 1013 ASSERT(compare->value()->representation().IsTagged()); |
| 1016 | 1014 |
| 1017 return new LHasCachedArrayIndexAndBranch( | 1015 return new LHasCachedArrayIndexAndBranch( |
| 1018 UseRegisterAtStart(compare->value()), first_id, second_id); | 1016 UseRegisterAtStart(compare->value())); |
| 1019 } else if (v->IsIsNull()) { | 1017 } else if (v->IsIsNull()) { |
| 1020 HIsNull* compare = HIsNull::cast(v); | 1018 HIsNull* compare = HIsNull::cast(v); |
| 1021 ASSERT(compare->value()->representation().IsTagged()); | 1019 ASSERT(compare->value()->representation().IsTagged()); |
| 1022 | 1020 |
| 1023 // We only need a temp register for non-strict compare. | 1021 // We only need a temp register for non-strict compare. |
| 1024 LOperand* temp = compare->is_strict() ? NULL : TempRegister(); | 1022 LOperand* temp = compare->is_strict() ? NULL : TempRegister(); |
| 1025 return new LIsNullAndBranch(UseRegisterAtStart(compare->value()), | 1023 return new LIsNullAndBranch(UseRegisterAtStart(compare->value()), |
| 1026 temp, | 1024 temp); |
| 1027 first_id, | |
| 1028 second_id); | |
| 1029 } else if (v->IsIsObject()) { | 1025 } else if (v->IsIsObject()) { |
| 1030 HIsObject* compare = HIsObject::cast(v); | 1026 HIsObject* compare = HIsObject::cast(v); |
| 1031 ASSERT(compare->value()->representation().IsTagged()); | 1027 ASSERT(compare->value()->representation().IsTagged()); |
| 1032 | 1028 |
| 1033 LOperand* temp1 = TempRegister(); | 1029 LOperand* temp1 = TempRegister(); |
| 1034 LOperand* temp2 = TempRegister(); | 1030 LOperand* temp2 = TempRegister(); |
| 1035 return new LIsObjectAndBranch(UseRegisterAtStart(compare->value()), | 1031 return new LIsObjectAndBranch(UseRegisterAtStart(compare->value()), |
| 1036 temp1, | 1032 temp1, |
| 1037 temp2, | 1033 temp2); |
| 1038 first_id, | |
| 1039 second_id); | |
| 1040 } else if (v->IsCompareJSObjectEq()) { | 1034 } else if (v->IsCompareJSObjectEq()) { |
| 1041 HCompareJSObjectEq* compare = HCompareJSObjectEq::cast(v); | 1035 HCompareJSObjectEq* compare = HCompareJSObjectEq::cast(v); |
| 1042 return new LCmpJSObjectEqAndBranch(UseRegisterAtStart(compare->left()), | 1036 return new LCmpJSObjectEqAndBranch(UseRegisterAtStart(compare->left()), |
| 1043 UseRegisterAtStart(compare->right()), | 1037 UseRegisterAtStart(compare->right())); |
| 1044 first_id, | |
| 1045 second_id); | |
| 1046 } else if (v->IsInstanceOf()) { | 1038 } else if (v->IsInstanceOf()) { |
| 1047 HInstanceOf* instance_of = HInstanceOf::cast(v); | 1039 HInstanceOf* instance_of = HInstanceOf::cast(v); |
| 1048 LInstanceOfAndBranch* result = | 1040 LInstanceOfAndBranch* result = |
| 1049 new LInstanceOfAndBranch( | 1041 new LInstanceOfAndBranch( |
| 1050 UseFixed(instance_of->left(), InstanceofStub::left()), | 1042 UseFixed(instance_of->left(), InstanceofStub::left()), |
| 1051 UseFixed(instance_of->right(), InstanceofStub::right()), | 1043 UseFixed(instance_of->right(), InstanceofStub::right())); |
| 1052 first_id, | |
| 1053 second_id); | |
| 1054 return MarkAsCall(result, instr); | 1044 return MarkAsCall(result, instr); |
| 1055 } else if (v->IsTypeofIs()) { | 1045 } else if (v->IsTypeofIs()) { |
| 1056 HTypeofIs* typeof_is = HTypeofIs::cast(v); | 1046 HTypeofIs* typeof_is = HTypeofIs::cast(v); |
| 1057 return new LTypeofIsAndBranch(UseTempRegister(typeof_is->value()), | 1047 return new LTypeofIsAndBranch(UseTempRegister(typeof_is->value())); |
| 1058 first_id, | |
| 1059 second_id); | |
| 1060 } else { | 1048 } else { |
| 1061 if (v->IsConstant()) { | 1049 if (v->IsConstant()) { |
| 1062 if (HConstant::cast(v)->handle()->IsTrue()) { | 1050 if (HConstant::cast(v)->handle()->IsTrue()) { |
| 1063 return new LGoto(first_id); | 1051 return new LGoto(instr->FirstSuccessor()->block_id()); |
| 1064 } else if (HConstant::cast(v)->handle()->IsFalse()) { | 1052 } else if (HConstant::cast(v)->handle()->IsFalse()) { |
| 1065 return new LGoto(second_id); | 1053 return new LGoto(instr->SecondSuccessor()->block_id()); |
| 1066 } | 1054 } |
| 1067 } | 1055 } |
| 1068 Abort("Undefined compare before branch"); | 1056 Abort("Undefined compare before branch"); |
| 1069 return NULL; | 1057 return NULL; |
| 1070 } | 1058 } |
| 1071 } | 1059 } |
| 1072 return new LBranch(UseRegisterAtStart(v), first_id, second_id); | 1060 return new LBranch(UseRegisterAtStart(v)); |
| 1073 } | 1061 } |
| 1074 | 1062 |
| 1075 | 1063 |
| 1076 LInstruction* LChunkBuilder::DoCompareMapAndBranch( | 1064 LInstruction* LChunkBuilder::DoCompareMapAndBranch( |
| 1077 HCompareMapAndBranch* instr) { | 1065 HCompareMapAndBranch* instr) { |
| 1078 ASSERT(instr->value()->representation().IsTagged()); | 1066 ASSERT(instr->value()->representation().IsTagged()); |
| 1079 LOperand* value = UseRegisterAtStart(instr->value()); | 1067 LOperand* value = UseRegisterAtStart(instr->value()); |
| 1080 return new LCmpMapAndBranch(value); | 1068 return new LCmpMapAndBranch(value); |
| 1081 } | 1069 } |
| 1082 | 1070 |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1171 UNREACHABLE(); | 1159 UNREACHABLE(); |
| 1172 return NULL; | 1160 return NULL; |
| 1173 } | 1161 } |
| 1174 } | 1162 } |
| 1175 } | 1163 } |
| 1176 | 1164 |
| 1177 | 1165 |
| 1178 LInstruction* LChunkBuilder::DoCallKeyed(HCallKeyed* instr) { | 1166 LInstruction* LChunkBuilder::DoCallKeyed(HCallKeyed* instr) { |
| 1179 ASSERT(instr->key()->representation().IsTagged()); | 1167 ASSERT(instr->key()->representation().IsTagged()); |
| 1180 argument_count_ -= instr->argument_count(); | 1168 argument_count_ -= instr->argument_count(); |
| 1181 UseFixed(instr->key(), ecx); | 1169 LOperand* key = UseFixed(instr->key(), ecx); |
| 1182 return MarkAsCall(DefineFixed(new LCallKeyed, eax), instr); | 1170 return MarkAsCall(DefineFixed(new LCallKeyed(key), eax), instr); |
| 1183 } | 1171 } |
| 1184 | 1172 |
| 1185 | 1173 |
| 1186 LInstruction* LChunkBuilder::DoCallNamed(HCallNamed* instr) { | 1174 LInstruction* LChunkBuilder::DoCallNamed(HCallNamed* instr) { |
| 1187 argument_count_ -= instr->argument_count(); | 1175 argument_count_ -= instr->argument_count(); |
| 1188 return MarkAsCall(DefineFixed(new LCallNamed, eax), instr); | 1176 return MarkAsCall(DefineFixed(new LCallNamed, eax), instr); |
| 1189 } | 1177 } |
| 1190 | 1178 |
| 1191 | 1179 |
| 1192 LInstruction* LChunkBuilder::DoCallGlobal(HCallGlobal* instr) { | 1180 LInstruction* LChunkBuilder::DoCallGlobal(HCallGlobal* instr) { |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1259 return DoBit(Token::BIT_XOR, instr); | 1247 return DoBit(Token::BIT_XOR, instr); |
| 1260 } | 1248 } |
| 1261 | 1249 |
| 1262 | 1250 |
| 1263 LInstruction* LChunkBuilder::DoDiv(HDiv* instr) { | 1251 LInstruction* LChunkBuilder::DoDiv(HDiv* instr) { |
| 1264 if (instr->representation().IsDouble()) { | 1252 if (instr->representation().IsDouble()) { |
| 1265 return DoArithmeticD(Token::DIV, instr); | 1253 return DoArithmeticD(Token::DIV, instr); |
| 1266 } else if (instr->representation().IsInteger32()) { | 1254 } else if (instr->representation().IsInteger32()) { |
| 1267 // The temporary operand is necessary to ensure that right is not allocated | 1255 // The temporary operand is necessary to ensure that right is not allocated |
| 1268 // into edx. | 1256 // into edx. |
| 1269 FixedTemp(edx); | 1257 LOperand* temp = FixedTemp(edx); |
| 1270 LOperand* value = UseFixed(instr->left(), eax); | 1258 LOperand* value = UseFixed(instr->left(), eax); |
| 1271 LOperand* divisor = UseRegister(instr->right()); | 1259 LOperand* divisor = UseRegister(instr->right()); |
| 1272 return AssignEnvironment(DefineFixed(new LDivI(value, divisor), eax)); | 1260 LDivI* result = new LDivI(value, divisor, temp); |
| 1261 return AssignEnvironment(DefineFixed(result, eax)); |
| 1273 } else { | 1262 } else { |
| 1274 ASSERT(instr->representation().IsTagged()); | 1263 ASSERT(instr->representation().IsTagged()); |
| 1275 return DoArithmeticT(Token::DIV, instr); | 1264 return DoArithmeticT(Token::DIV, instr); |
| 1276 } | 1265 } |
| 1277 } | 1266 } |
| 1278 | 1267 |
| 1279 | 1268 |
| 1280 LInstruction* LChunkBuilder::DoMod(HMod* instr) { | 1269 LInstruction* LChunkBuilder::DoMod(HMod* instr) { |
| 1281 if (instr->representation().IsInteger32()) { | 1270 if (instr->representation().IsInteger32()) { |
| 1282 ASSERT(instr->left()->representation().IsInteger32()); | 1271 ASSERT(instr->left()->representation().IsInteger32()); |
| 1283 ASSERT(instr->right()->representation().IsInteger32()); | 1272 ASSERT(instr->right()->representation().IsInteger32()); |
| 1284 // The temporary operand is necessary to ensure that right is not allocated | 1273 // The temporary operand is necessary to ensure that right is not allocated |
| 1285 // into edx. | 1274 // into edx. |
| 1286 FixedTemp(edx); | 1275 LOperand* temp = FixedTemp(edx); |
| 1287 LOperand* value = UseFixed(instr->left(), eax); | 1276 LOperand* value = UseFixed(instr->left(), eax); |
| 1288 LOperand* divisor = UseRegister(instr->right()); | 1277 LOperand* divisor = UseRegister(instr->right()); |
| 1289 LModI* mod = new LModI(value, divisor); | 1278 LModI* mod = new LModI(value, divisor, temp); |
| 1290 LInstruction* result = DefineFixed(mod, edx); | 1279 LInstruction* result = DefineFixed(mod, edx); |
| 1291 return (instr->CheckFlag(HValue::kBailoutOnMinusZero) || | 1280 return (instr->CheckFlag(HValue::kBailoutOnMinusZero) || |
| 1292 instr->CheckFlag(HValue::kCanBeDivByZero)) | 1281 instr->CheckFlag(HValue::kCanBeDivByZero)) |
| 1293 ? AssignEnvironment(result) | 1282 ? AssignEnvironment(result) |
| 1294 : result; | 1283 : result; |
| 1295 } else if (instr->representation().IsTagged()) { | 1284 } else if (instr->representation().IsTagged()) { |
| 1296 return DoArithmeticT(Token::MOD, instr); | 1285 return DoArithmeticT(Token::MOD, instr); |
| 1297 } else { | 1286 } else { |
| 1298 ASSERT(instr->representation().IsDouble()); | 1287 ASSERT(instr->representation().IsDouble()); |
| 1299 // We call a C function for double modulo. It can't trigger a GC. | 1288 // We call a C function for double modulo. It can't trigger a GC. |
| (...skipping 583 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1883 LInstruction* LChunkBuilder::DoLeaveInlined(HLeaveInlined* instr) { | 1872 LInstruction* LChunkBuilder::DoLeaveInlined(HLeaveInlined* instr) { |
| 1884 HEnvironment* outer = current_block_->last_environment()->outer(); | 1873 HEnvironment* outer = current_block_->last_environment()->outer(); |
| 1885 current_block_->UpdateEnvironment(outer); | 1874 current_block_->UpdateEnvironment(outer); |
| 1886 return NULL; | 1875 return NULL; |
| 1887 } | 1876 } |
| 1888 | 1877 |
| 1889 | 1878 |
| 1890 } } // namespace v8::internal | 1879 } } // namespace v8::internal |
| 1891 | 1880 |
| 1892 #endif // V8_TARGET_ARCH_IA32 | 1881 #endif // V8_TARGET_ARCH_IA32 |
| OLD | NEW |