| 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 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 57 | 57 |
| 58 | 58 |
| 59 void LOsrEntry::MarkSpilledDoubleRegister(int allocation_index, | 59 void LOsrEntry::MarkSpilledDoubleRegister(int allocation_index, |
| 60 LOperand* spill_operand) { | 60 LOperand* spill_operand) { |
| 61 ASSERT(spill_operand->IsDoubleStackSlot()); | 61 ASSERT(spill_operand->IsDoubleStackSlot()); |
| 62 ASSERT(double_register_spills_[allocation_index] == NULL); | 62 ASSERT(double_register_spills_[allocation_index] == NULL); |
| 63 double_register_spills_[allocation_index] = spill_operand; | 63 double_register_spills_[allocation_index] = spill_operand; |
| 64 } | 64 } |
| 65 | 65 |
| 66 | 66 |
| 67 void LInstruction::PrintTo(StringStream* stream) const { | 67 void LInstruction::PrintTo(StringStream* stream) { |
| 68 stream->Add("%s ", this->Mnemonic()); | 68 stream->Add("%s ", this->Mnemonic()); |
| 69 if (HasResult()) { | 69 if (HasResult()) { |
| 70 result()->PrintTo(stream); | 70 PrintOutputOperandTo(stream); |
| 71 stream->Add(" "); | |
| 72 } | 71 } |
| 72 |
| 73 PrintDataTo(stream); | 73 PrintDataTo(stream); |
| 74 | 74 |
| 75 if (HasEnvironment()) { | 75 if (HasEnvironment()) { |
| 76 stream->Add(" "); | 76 stream->Add(" "); |
| 77 environment()->PrintTo(stream); | 77 environment()->PrintTo(stream); |
| 78 } | 78 } |
| 79 | 79 |
| 80 if (HasPointerMap()) { | 80 if (HasPointerMap()) { |
| 81 stream->Add(" "); | 81 stream->Add(" "); |
| 82 pointer_map()->PrintTo(stream); | 82 pointer_map()->PrintTo(stream); |
| 83 } | 83 } |
| 84 } | 84 } |
| 85 | 85 |
| 86 | 86 |
| 87 void LLabel::PrintDataTo(StringStream* stream) const { | 87 template<int R, int I, int T> |
| 88 void LTemplateInstruction<R, I, T>::PrintDataTo(StringStream* stream) { |
| 89 stream->Add("= "); |
| 90 inputs_.PrintOperandsTo(stream); |
| 91 } |
| 92 |
| 93 |
| 94 template<int R, int I, int T> |
| 95 void LTemplateInstruction<R, I, T>::PrintOutputOperandTo(StringStream* stream) { |
| 96 results_.PrintOperandsTo(stream); |
| 97 } |
| 98 |
| 99 |
| 100 template<typename T, int N> |
| 101 void OperandContainer<T, N>::PrintOperandsTo(StringStream* stream) { |
| 102 for (int i = 0; i < N; i++) { |
| 103 if (i > 0) stream->Add(" "); |
| 104 elems_[i]->PrintTo(stream); |
| 105 } |
| 106 } |
| 107 |
| 108 |
| 109 void LLabel::PrintDataTo(StringStream* stream) { |
| 88 LGap::PrintDataTo(stream); | 110 LGap::PrintDataTo(stream); |
| 89 LLabel* rep = replacement(); | 111 LLabel* rep = replacement(); |
| 90 if (rep != NULL) { | 112 if (rep != NULL) { |
| 91 stream->Add(" Dead block replaced with B%d", rep->block_id()); | 113 stream->Add(" Dead block replaced with B%d", rep->block_id()); |
| 92 } | 114 } |
| 93 } | 115 } |
| 94 | 116 |
| 95 | 117 |
| 96 bool LGap::IsRedundant() const { | 118 bool LGap::IsRedundant() const { |
| 97 for (int i = 0; i < 4; i++) { | 119 for (int i = 0; i < 4; i++) { |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 136 case Token::MUL: return "mul-t"; | 158 case Token::MUL: return "mul-t"; |
| 137 case Token::MOD: return "mod-t"; | 159 case Token::MOD: return "mod-t"; |
| 138 case Token::DIV: return "div-t"; | 160 case Token::DIV: return "div-t"; |
| 139 default: | 161 default: |
| 140 UNREACHABLE(); | 162 UNREACHABLE(); |
| 141 return NULL; | 163 return NULL; |
| 142 } | 164 } |
| 143 } | 165 } |
| 144 | 166 |
| 145 | 167 |
| 146 | 168 void LGoto::PrintDataTo(StringStream* stream) { |
| 147 void LBinaryOperation::PrintDataTo(StringStream* stream) const { | |
| 148 stream->Add("= "); | |
| 149 left()->PrintTo(stream); | |
| 150 stream->Add(" "); | |
| 151 right()->PrintTo(stream); | |
| 152 } | |
| 153 | |
| 154 | |
| 155 void LGoto::PrintDataTo(StringStream* stream) const { | |
| 156 stream->Add("B%d", block_id()); | 169 stream->Add("B%d", block_id()); |
| 157 } | 170 } |
| 158 | 171 |
| 159 | 172 |
| 160 void LBranch::PrintDataTo(StringStream* stream) const { | 173 void LBranch::PrintDataTo(StringStream* stream) { |
| 161 stream->Add("B%d | B%d on ", true_block_id(), false_block_id()); | 174 stream->Add("B%d | B%d on ", true_block_id(), false_block_id()); |
| 162 input()->PrintTo(stream); | 175 InputAt(0)->PrintTo(stream); |
| 163 } | 176 } |
| 164 | 177 |
| 165 | 178 |
| 166 void LCmpIDAndBranch::PrintDataTo(StringStream* stream) const { | 179 void LCmpIDAndBranch::PrintDataTo(StringStream* stream) { |
| 167 stream->Add("if "); | 180 stream->Add("if "); |
| 168 left()->PrintTo(stream); | 181 InputAt(0)->PrintTo(stream); |
| 169 stream->Add(" %s ", Token::String(op())); | 182 stream->Add(" %s ", Token::String(op())); |
| 170 right()->PrintTo(stream); | 183 InputAt(1)->PrintTo(stream); |
| 171 stream->Add(" then B%d else B%d", true_block_id(), false_block_id()); | 184 stream->Add(" then B%d else B%d", true_block_id(), false_block_id()); |
| 172 } | 185 } |
| 173 | 186 |
| 174 | 187 |
| 175 void LIsNullAndBranch::PrintDataTo(StringStream* stream) const { | 188 void LIsNullAndBranch::PrintDataTo(StringStream* stream) { |
| 176 stream->Add("if "); | 189 stream->Add("if "); |
| 177 input()->PrintTo(stream); | 190 InputAt(0)->PrintTo(stream); |
| 178 stream->Add(is_strict() ? " === null" : " == null"); | 191 stream->Add(is_strict() ? " === null" : " == null"); |
| 179 stream->Add(" then B%d else B%d", true_block_id(), false_block_id()); | 192 stream->Add(" then B%d else B%d", true_block_id(), false_block_id()); |
| 180 } | 193 } |
| 181 | 194 |
| 182 | 195 |
| 183 void LIsObjectAndBranch::PrintDataTo(StringStream* stream) const { | 196 void LIsObjectAndBranch::PrintDataTo(StringStream* stream) { |
| 184 stream->Add("if is_object("); | 197 stream->Add("if is_object("); |
| 185 input()->PrintTo(stream); | 198 InputAt(0)->PrintTo(stream); |
| 186 stream->Add(") then B%d else B%d", true_block_id(), false_block_id()); | 199 stream->Add(") then B%d else B%d", true_block_id(), false_block_id()); |
| 187 } | 200 } |
| 188 | 201 |
| 189 | 202 |
| 190 void LIsSmiAndBranch::PrintDataTo(StringStream* stream) const { | 203 void LIsSmiAndBranch::PrintDataTo(StringStream* stream) { |
| 191 stream->Add("if is_smi("); | 204 stream->Add("if is_smi("); |
| 192 input()->PrintTo(stream); | 205 InputAt(0)->PrintTo(stream); |
| 193 stream->Add(") then B%d else B%d", true_block_id(), false_block_id()); | 206 stream->Add(") then B%d else B%d", true_block_id(), false_block_id()); |
| 194 } | 207 } |
| 195 | 208 |
| 196 | 209 |
| 197 void LHasInstanceTypeAndBranch::PrintDataTo(StringStream* stream) const { | 210 void LHasInstanceTypeAndBranch::PrintDataTo(StringStream* stream) { |
| 198 stream->Add("if has_instance_type("); | 211 stream->Add("if has_instance_type("); |
| 199 input()->PrintTo(stream); | 212 InputAt(0)->PrintTo(stream); |
| 200 stream->Add(") then B%d else B%d", true_block_id(), false_block_id()); | 213 stream->Add(") then B%d else B%d", true_block_id(), false_block_id()); |
| 201 } | 214 } |
| 202 | 215 |
| 203 | 216 |
| 204 void LHasCachedArrayIndexAndBranch::PrintDataTo(StringStream* stream) const { | 217 void LHasCachedArrayIndexAndBranch::PrintDataTo(StringStream* stream) { |
| 205 stream->Add("if has_cached_array_index("); | 218 stream->Add("if has_cached_array_index("); |
| 206 input()->PrintTo(stream); | 219 InputAt(0)->PrintTo(stream); |
| 207 stream->Add(") then B%d else B%d", true_block_id(), false_block_id()); | 220 stream->Add(") then B%d else B%d", true_block_id(), false_block_id()); |
| 208 } | 221 } |
| 209 | 222 |
| 210 | 223 |
| 211 void LClassOfTestAndBranch::PrintDataTo(StringStream* stream) const { | 224 void LClassOfTestAndBranch::PrintDataTo(StringStream* stream) { |
| 212 stream->Add("if class_of_test("); | 225 stream->Add("if class_of_test("); |
| 213 input()->PrintTo(stream); | 226 InputAt(0)->PrintTo(stream); |
| 214 stream->Add(", \"%o\") then B%d else B%d", | 227 stream->Add(", \"%o\") then B%d else B%d", |
| 215 *hydrogen()->class_name(), | 228 *hydrogen()->class_name(), |
| 216 true_block_id(), | 229 true_block_id(), |
| 217 false_block_id()); | 230 false_block_id()); |
| 218 } | 231 } |
| 219 | 232 |
| 220 | 233 |
| 221 void LTypeofIs::PrintDataTo(StringStream* stream) const { | 234 void LTypeofIs::PrintDataTo(StringStream* stream) { |
| 222 input()->PrintTo(stream); | 235 InputAt(0)->PrintTo(stream); |
| 223 stream->Add(" == \"%s\"", *hydrogen()->type_literal()->ToCString()); | 236 stream->Add(" == \"%s\"", *hydrogen()->type_literal()->ToCString()); |
| 224 } | 237 } |
| 225 | 238 |
| 226 | 239 |
| 227 void LTypeofIsAndBranch::PrintDataTo(StringStream* stream) const { | 240 void LTypeofIsAndBranch::PrintDataTo(StringStream* stream) { |
| 228 stream->Add("if typeof "); | 241 stream->Add("if typeof "); |
| 229 input()->PrintTo(stream); | 242 InputAt(0)->PrintTo(stream); |
| 230 stream->Add(" == \"%s\" then B%d else B%d", | 243 stream->Add(" == \"%s\" then B%d else B%d", |
| 231 *hydrogen()->type_literal()->ToCString(), | 244 *hydrogen()->type_literal()->ToCString(), |
| 232 true_block_id(), false_block_id()); | 245 true_block_id(), false_block_id()); |
| 233 } | 246 } |
| 234 | 247 |
| 235 | 248 |
| 236 void LCallConstantFunction::PrintDataTo(StringStream* stream) const { | 249 void LCallConstantFunction::PrintDataTo(StringStream* stream) { |
| 237 stream->Add("#%d / ", arity()); | 250 stream->Add("#%d / ", arity()); |
| 238 } | 251 } |
| 239 | 252 |
| 240 | 253 |
| 241 void LUnaryMathOperation::PrintDataTo(StringStream* stream) const { | 254 void LUnaryMathOperation::PrintDataTo(StringStream* stream) { |
| 242 stream->Add("/%s ", hydrogen()->OpName()); | 255 stream->Add("/%s ", hydrogen()->OpName()); |
| 243 input()->PrintTo(stream); | 256 InputAt(0)->PrintTo(stream); |
| 244 } | 257 } |
| 245 | 258 |
| 246 | 259 |
| 247 void LCallKeyed::PrintDataTo(StringStream* stream) const { | 260 void LLoadContextSlot::PrintDataTo(StringStream* stream) { |
| 261 stream->Add("(%d, %d)", context_chain_length(), slot_index()); |
| 262 } |
| 263 |
| 264 |
| 265 void LCallKeyed::PrintDataTo(StringStream* stream) { |
| 248 stream->Add("[r2] #%d / ", arity()); | 266 stream->Add("[r2] #%d / ", arity()); |
| 249 } | 267 } |
| 250 | 268 |
| 251 | 269 |
| 252 void LCallNamed::PrintDataTo(StringStream* stream) const { | 270 void LCallNamed::PrintDataTo(StringStream* stream) { |
| 253 SmartPointer<char> name_string = name()->ToCString(); | 271 SmartPointer<char> name_string = name()->ToCString(); |
| 254 stream->Add("%s #%d / ", *name_string, arity()); | 272 stream->Add("%s #%d / ", *name_string, arity()); |
| 255 } | 273 } |
| 256 | 274 |
| 257 | 275 |
| 258 void LCallGlobal::PrintDataTo(StringStream* stream) const { | 276 void LCallGlobal::PrintDataTo(StringStream* stream) { |
| 259 SmartPointer<char> name_string = name()->ToCString(); | 277 SmartPointer<char> name_string = name()->ToCString(); |
| 260 stream->Add("%s #%d / ", *name_string, arity()); | 278 stream->Add("%s #%d / ", *name_string, arity()); |
| 261 } | 279 } |
| 262 | 280 |
| 263 | 281 |
| 264 void LCallKnownGlobal::PrintDataTo(StringStream* stream) const { | 282 void LCallKnownGlobal::PrintDataTo(StringStream* stream) { |
| 265 stream->Add("#%d / ", arity()); | 283 stream->Add("#%d / ", arity()); |
| 266 } | 284 } |
| 267 | 285 |
| 268 | 286 |
| 269 void LCallNew::PrintDataTo(StringStream* stream) const { | 287 void LCallNew::PrintDataTo(StringStream* stream) { |
| 270 LUnaryOperation::PrintDataTo(stream); | 288 stream->Add("= "); |
| 289 InputAt(0)->PrintTo(stream); |
| 271 stream->Add(" #%d / ", arity()); | 290 stream->Add(" #%d / ", arity()); |
| 272 } | 291 } |
| 273 | 292 |
| 274 | 293 |
| 275 void LClassOfTest::PrintDataTo(StringStream* stream) const { | 294 void LClassOfTest::PrintDataTo(StringStream* stream) { |
| 276 stream->Add("= class_of_test("); | 295 stream->Add("= class_of_test("); |
| 277 input()->PrintTo(stream); | 296 InputAt(0)->PrintTo(stream); |
| 278 stream->Add(", \"%o\")", *hydrogen()->class_name()); | 297 stream->Add(", \"%o\")", *hydrogen()->class_name()); |
| 279 } | 298 } |
| 280 | 299 |
| 281 | 300 |
| 282 void LUnaryOperation::PrintDataTo(StringStream* stream) const { | 301 void LAccessArgumentsAt::PrintDataTo(StringStream* stream) { |
| 283 stream->Add("= "); | |
| 284 input()->PrintTo(stream); | |
| 285 } | |
| 286 | |
| 287 | |
| 288 void LAccessArgumentsAt::PrintDataTo(StringStream* stream) const { | |
| 289 arguments()->PrintTo(stream); | 302 arguments()->PrintTo(stream); |
| 290 | 303 |
| 291 stream->Add(" length "); | 304 stream->Add(" length "); |
| 292 length()->PrintTo(stream); | 305 length()->PrintTo(stream); |
| 293 | 306 |
| 294 stream->Add(" index "); | 307 stream->Add(" index "); |
| 295 index()->PrintTo(stream); | 308 index()->PrintTo(stream); |
| 296 } | 309 } |
| 297 | 310 |
| 298 | 311 |
| 312 void LStoreNamed::PrintDataTo(StringStream* stream) { |
| 313 object()->PrintTo(stream); |
| 314 stream->Add("."); |
| 315 stream->Add(*String::cast(*name())->ToCString()); |
| 316 stream->Add(" <- "); |
| 317 value()->PrintTo(stream); |
| 318 } |
| 319 |
| 320 |
| 321 void LStoreKeyed::PrintDataTo(StringStream* stream) { |
| 322 object()->PrintTo(stream); |
| 323 stream->Add("["); |
| 324 key()->PrintTo(stream); |
| 325 stream->Add("] <- "); |
| 326 value()->PrintTo(stream); |
| 327 } |
| 328 |
| 329 |
| 299 LChunk::LChunk(HGraph* graph) | 330 LChunk::LChunk(HGraph* graph) |
| 300 : spill_slot_count_(0), | 331 : spill_slot_count_(0), |
| 301 graph_(graph), | 332 graph_(graph), |
| 302 instructions_(32), | 333 instructions_(32), |
| 303 pointer_maps_(8), | 334 pointer_maps_(8), |
| 304 inlined_closures_(1) { | 335 inlined_closures_(1) { |
| 305 } | 336 } |
| 306 | 337 |
| 307 | 338 |
| 308 void LChunk::Verify() const { | |
| 309 // TODO(twuerthinger): Implement verification for chunk. | |
| 310 } | |
| 311 | |
| 312 | |
| 313 int LChunk::GetNextSpillIndex(bool is_double) { | 339 int LChunk::GetNextSpillIndex(bool is_double) { |
| 314 // Skip a slot if for a double-width slot. | 340 // Skip a slot if for a double-width slot. |
| 315 if (is_double) spill_slot_count_++; | 341 if (is_double) spill_slot_count_++; |
| 316 return spill_slot_count_++; | 342 return spill_slot_count_++; |
| 317 } | 343 } |
| 318 | 344 |
| 319 | 345 |
| 320 LOperand* LChunk::GetNextSpillSlot(bool is_double) { | 346 LOperand* LChunk::GetNextSpillSlot(bool is_double) { |
| 321 int index = GetNextSpillIndex(is_double); | 347 int index = GetNextSpillIndex(is_double); |
| 322 if (is_double) { | 348 if (is_double) { |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 357 | 383 |
| 358 if (can_eliminate) { | 384 if (can_eliminate) { |
| 359 label->set_replacement(GetLabel(goto_instr->block_id())); | 385 label->set_replacement(GetLabel(goto_instr->block_id())); |
| 360 } | 386 } |
| 361 } | 387 } |
| 362 } | 388 } |
| 363 } | 389 } |
| 364 } | 390 } |
| 365 | 391 |
| 366 | 392 |
| 367 void LStoreNamed::PrintDataTo(StringStream* stream) const { | |
| 368 object()->PrintTo(stream); | |
| 369 stream->Add("."); | |
| 370 stream->Add(*String::cast(*name())->ToCString()); | |
| 371 stream->Add(" <- "); | |
| 372 value()->PrintTo(stream); | |
| 373 } | |
| 374 | |
| 375 | |
| 376 void LStoreKeyed::PrintDataTo(StringStream* stream) const { | |
| 377 object()->PrintTo(stream); | |
| 378 stream->Add("["); | |
| 379 key()->PrintTo(stream); | |
| 380 stream->Add("] <- "); | |
| 381 value()->PrintTo(stream); | |
| 382 } | |
| 383 | |
| 384 | |
| 385 int LChunk::AddInstruction(LInstruction* instr, HBasicBlock* block) { | 393 int LChunk::AddInstruction(LInstruction* instr, HBasicBlock* block) { |
| 386 LGap* gap = new LGap(block); | 394 LGap* gap = new LGap(block); |
| 387 int index = -1; | 395 int index = -1; |
| 388 if (instr->IsControl()) { | 396 if (instr->IsControl()) { |
| 389 instructions_.Add(gap); | 397 instructions_.Add(gap); |
| 390 index = instructions_.length(); | 398 index = instructions_.length(); |
| 391 instructions_.Add(instr); | 399 instructions_.Add(instr); |
| 392 } else { | 400 } else { |
| 393 index = instructions_.length(); | 401 index = instructions_.length(); |
| 394 instructions_.Add(instr); | 402 instructions_.Add(instr); |
| (...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 564 } | 572 } |
| 565 | 573 |
| 566 | 574 |
| 567 LOperand* LChunkBuilder::UseRegisterOrConstantAtStart(HValue* value) { | 575 LOperand* LChunkBuilder::UseRegisterOrConstantAtStart(HValue* value) { |
| 568 return value->IsConstant() | 576 return value->IsConstant() |
| 569 ? chunk_->DefineConstantOperand(HConstant::cast(value)) | 577 ? chunk_->DefineConstantOperand(HConstant::cast(value)) |
| 570 : UseRegisterAtStart(value); | 578 : UseRegisterAtStart(value); |
| 571 } | 579 } |
| 572 | 580 |
| 573 | 581 |
| 582 LOperand* LChunkBuilder::UseAny(HValue* value) { |
| 583 return value->IsConstant() |
| 584 ? chunk_->DefineConstantOperand(HConstant::cast(value)) |
| 585 : Use(value, new LUnallocated(LUnallocated::ANY)); |
| 586 } |
| 587 |
| 588 |
| 574 LOperand* LChunkBuilder::Use(HValue* value, LUnallocated* operand) { | 589 LOperand* LChunkBuilder::Use(HValue* value, LUnallocated* operand) { |
| 575 if (value->EmitAtUses()) { | 590 if (value->EmitAtUses()) { |
| 576 HInstruction* instr = HInstruction::cast(value); | 591 HInstruction* instr = HInstruction::cast(value); |
| 577 VisitInstruction(instr); | 592 VisitInstruction(instr); |
| 578 } | 593 } |
| 579 allocator_->RecordUse(value, operand); | 594 allocator_->RecordUse(value, operand); |
| 580 return operand; | 595 return operand; |
| 581 } | 596 } |
| 582 | 597 |
| 583 | 598 |
| 584 LInstruction* LChunkBuilder::Define(LInstruction* instr) { | 599 template<int I, int T> |
| 600 LInstruction* LChunkBuilder::Define(LTemplateInstruction<1, I, T>* instr, |
| 601 LUnallocated* result) { |
| 602 allocator_->RecordDefinition(current_instruction_, result); |
| 603 instr->set_result(result); |
| 604 return instr; |
| 605 } |
| 606 |
| 607 |
| 608 template<int I, int T> |
| 609 LInstruction* LChunkBuilder::Define(LTemplateInstruction<1, I, T>* instr) { |
| 585 return Define(instr, new LUnallocated(LUnallocated::NONE)); | 610 return Define(instr, new LUnallocated(LUnallocated::NONE)); |
| 586 } | 611 } |
| 587 | 612 |
| 588 | 613 |
| 589 LInstruction* LChunkBuilder::DefineAsRegister(LInstruction* instr) { | 614 template<int I, int T> |
| 615 LInstruction* LChunkBuilder::DefineAsRegister( |
| 616 LTemplateInstruction<1, I, T>* instr) { |
| 590 return Define(instr, new LUnallocated(LUnallocated::MUST_HAVE_REGISTER)); | 617 return Define(instr, new LUnallocated(LUnallocated::MUST_HAVE_REGISTER)); |
| 591 } | 618 } |
| 592 | 619 |
| 593 | 620 |
| 594 LInstruction* LChunkBuilder::DefineAsSpilled(LInstruction* instr, int index) { | 621 template<int I, int T> |
| 622 LInstruction* LChunkBuilder::DefineAsSpilled( |
| 623 LTemplateInstruction<1, I, T>* instr, int index) { |
| 595 return Define(instr, new LUnallocated(LUnallocated::FIXED_SLOT, index)); | 624 return Define(instr, new LUnallocated(LUnallocated::FIXED_SLOT, index)); |
| 596 } | 625 } |
| 597 | 626 |
| 598 | 627 |
| 599 LInstruction* LChunkBuilder::DefineSameAsFirst(LInstruction* instr) { | 628 template<int I, int T> |
| 629 LInstruction* LChunkBuilder::DefineSameAsFirst( |
| 630 LTemplateInstruction<1, I, T>* instr) { |
| 600 return Define(instr, new LUnallocated(LUnallocated::SAME_AS_FIRST_INPUT)); | 631 return Define(instr, new LUnallocated(LUnallocated::SAME_AS_FIRST_INPUT)); |
| 601 } | 632 } |
| 602 | 633 |
| 603 | 634 |
| 604 LInstruction* LChunkBuilder::DefineFixed(LInstruction* instr, Register reg) { | 635 template<int I, int T> |
| 636 LInstruction* LChunkBuilder::DefineFixed( |
| 637 LTemplateInstruction<1, I, T>* instr, Register reg) { |
| 605 return Define(instr, ToUnallocated(reg)); | 638 return Define(instr, ToUnallocated(reg)); |
| 606 } | 639 } |
| 607 | 640 |
| 608 | 641 |
| 609 LInstruction* LChunkBuilder::DefineFixedDouble(LInstruction* instr, | 642 template<int I, int T> |
| 610 DoubleRegister reg) { | 643 LInstruction* LChunkBuilder::DefineFixedDouble( |
| 644 LTemplateInstruction<1, I, T>* instr, DoubleRegister reg) { |
| 611 return Define(instr, ToUnallocated(reg)); | 645 return Define(instr, ToUnallocated(reg)); |
| 612 } | 646 } |
| 613 | 647 |
| 614 | 648 |
| 615 LInstruction* LChunkBuilder::AssignEnvironment(LInstruction* instr) { | 649 LInstruction* LChunkBuilder::AssignEnvironment(LInstruction* instr) { |
| 616 HEnvironment* hydrogen_env = current_block_->last_environment(); | 650 HEnvironment* hydrogen_env = current_block_->last_environment(); |
| 617 instr->set_environment(CreateEnvironment(hydrogen_env)); | 651 instr->set_environment(CreateEnvironment(hydrogen_env)); |
| 618 return instr; | 652 return instr; |
| 619 } | 653 } |
| 620 | 654 |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 655 bool needs_environment = | 689 bool needs_environment = |
| 656 (can_deoptimize == CAN_DEOPTIMIZE_EAGERLY) || !hinstr->HasSideEffects(); | 690 (can_deoptimize == CAN_DEOPTIMIZE_EAGERLY) || !hinstr->HasSideEffects(); |
| 657 if (needs_environment && !instr->HasEnvironment()) { | 691 if (needs_environment && !instr->HasEnvironment()) { |
| 658 instr = AssignEnvironment(instr); | 692 instr = AssignEnvironment(instr); |
| 659 } | 693 } |
| 660 | 694 |
| 661 return instr; | 695 return instr; |
| 662 } | 696 } |
| 663 | 697 |
| 664 | 698 |
| 699 LInstruction* LChunkBuilder::MarkAsSaveDoubles(LInstruction* instr) { |
| 700 allocator_->MarkAsSaveDoubles(); |
| 701 return instr; |
| 702 } |
| 703 |
| 704 |
| 665 LInstruction* LChunkBuilder::AssignPointerMap(LInstruction* instr) { | 705 LInstruction* LChunkBuilder::AssignPointerMap(LInstruction* instr) { |
| 666 ASSERT(!instr->HasPointerMap()); | 706 ASSERT(!instr->HasPointerMap()); |
| 667 instr->set_pointer_map(new LPointerMap(position_)); | 707 instr->set_pointer_map(new LPointerMap(position_)); |
| 668 return instr; | 708 return instr; |
| 669 } | 709 } |
| 670 | 710 |
| 671 | |
| 672 LInstruction* LChunkBuilder::Define(LInstruction* instr, LUnallocated* result) { | |
| 673 allocator_->RecordDefinition(current_instruction_, result); | |
| 674 instr->set_result(result); | |
| 675 return instr; | |
| 676 } | |
| 677 | |
| 678 | 711 |
| 679 LUnallocated* LChunkBuilder::TempRegister() { | 712 LUnallocated* LChunkBuilder::TempRegister() { |
| 680 LUnallocated* operand = new LUnallocated(LUnallocated::MUST_HAVE_REGISTER); | 713 LUnallocated* operand = new LUnallocated(LUnallocated::MUST_HAVE_REGISTER); |
| 681 allocator_->RecordTemporary(operand); | 714 allocator_->RecordTemporary(operand); |
| 682 return operand; | 715 return operand; |
| 683 } | 716 } |
| 684 | 717 |
| 685 | 718 |
| 686 LOperand* LChunkBuilder::FixedTemp(Register reg) { | 719 LOperand* LChunkBuilder::FixedTemp(Register reg) { |
| 687 LUnallocated* operand = ToUnallocated(reg); | 720 LUnallocated* operand = ToUnallocated(reg); |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 776 op == Token::DIV || | 809 op == Token::DIV || |
| 777 op == Token::MOD || | 810 op == Token::MOD || |
| 778 op == Token::MUL || | 811 op == Token::MUL || |
| 779 op == Token::SUB); | 812 op == Token::SUB); |
| 780 HValue* left = instr->left(); | 813 HValue* left = instr->left(); |
| 781 HValue* right = instr->right(); | 814 HValue* right = instr->right(); |
| 782 ASSERT(left->representation().IsTagged()); | 815 ASSERT(left->representation().IsTagged()); |
| 783 ASSERT(right->representation().IsTagged()); | 816 ASSERT(right->representation().IsTagged()); |
| 784 LOperand* left_operand = UseFixed(left, r1); | 817 LOperand* left_operand = UseFixed(left, r1); |
| 785 LOperand* right_operand = UseFixed(right, r0); | 818 LOperand* right_operand = UseFixed(right, r0); |
| 786 LInstruction* result = new LArithmeticT(op, left_operand, right_operand); | 819 LArithmeticT* result = new LArithmeticT(op, left_operand, right_operand); |
| 787 return MarkAsCall(DefineFixed(result, r0), instr); | 820 return MarkAsCall(DefineFixed(result, r0), instr); |
| 788 } | 821 } |
| 789 | 822 |
| 823 |
| 790 void LChunkBuilder::DoBasicBlock(HBasicBlock* block, HBasicBlock* next_block) { | 824 void LChunkBuilder::DoBasicBlock(HBasicBlock* block, HBasicBlock* next_block) { |
| 791 ASSERT(is_building()); | 825 ASSERT(is_building()); |
| 792 current_block_ = block; | 826 current_block_ = block; |
| 793 next_block_ = next_block; | 827 next_block_ = next_block; |
| 794 if (block->IsStartBlock()) { | 828 if (block->IsStartBlock()) { |
| 795 block->UpdateEnvironment(graph_->start_environment()); | 829 block->UpdateEnvironment(graph_->start_environment()); |
| 796 argument_count_ = 0; | 830 argument_count_ = 0; |
| 797 } else if (block->predecessors()->length() == 1) { | 831 } else if (block->predecessors()->length() == 1) { |
| 798 // We have a single predecessor => copy environment and outgoing | 832 // We have a single predecessor => copy environment and outgoing |
| 799 // argument count from the predecessor. | 833 // argument count from the predecessor. |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 857 if (current->has_position()) position_ = current->position(); | 891 if (current->has_position()) position_ = current->position(); |
| 858 LInstruction* instr = current->CompileToLithium(this); | 892 LInstruction* instr = current->CompileToLithium(this); |
| 859 | 893 |
| 860 if (instr != NULL) { | 894 if (instr != NULL) { |
| 861 if (FLAG_stress_pointer_maps && !instr->HasPointerMap()) { | 895 if (FLAG_stress_pointer_maps && !instr->HasPointerMap()) { |
| 862 instr = AssignPointerMap(instr); | 896 instr = AssignPointerMap(instr); |
| 863 } | 897 } |
| 864 if (FLAG_stress_environments && !instr->HasEnvironment()) { | 898 if (FLAG_stress_environments && !instr->HasEnvironment()) { |
| 865 instr = AssignEnvironment(instr); | 899 instr = AssignEnvironment(instr); |
| 866 } | 900 } |
| 867 if (current->IsBranch()) { | 901 if (current->IsTest() && !instr->IsGoto()) { |
| 868 instr->set_hydrogen_value(HBranch::cast(current)->value()); | 902 ASSERT(instr->IsControl()); |
| 903 HTest* test = HTest::cast(current); |
| 904 instr->set_hydrogen_value(test->value()); |
| 905 HBasicBlock* first = test->FirstSuccessor(); |
| 906 HBasicBlock* second = test->SecondSuccessor(); |
| 907 ASSERT(first != NULL && second != NULL); |
| 908 instr->SetBranchTargets(first->block_id(), second->block_id()); |
| 869 } else { | 909 } else { |
| 870 instr->set_hydrogen_value(current); | 910 instr->set_hydrogen_value(current); |
| 871 } | 911 } |
| 872 | 912 |
| 873 int index = chunk_->AddInstruction(instr, current_block_); | 913 int index = chunk_->AddInstruction(instr, current_block_); |
| 874 allocator_->SummarizeInstruction(index); | 914 allocator_->SummarizeInstruction(index); |
| 875 } else { | 915 } else { |
| 876 // This instruction should be omitted. | 916 // This instruction should be omitted. |
| 877 allocator_->OmitInstruction(); | 917 allocator_->OmitInstruction(); |
| 878 } | 918 } |
| (...skipping 16 matching lines...) Expand all Loading... |
| 895 outer); | 935 outer); |
| 896 int argument_index = 0; | 936 int argument_index = 0; |
| 897 for (int i = 0; i < value_count; ++i) { | 937 for (int i = 0; i < value_count; ++i) { |
| 898 HValue* value = hydrogen_env->values()->at(i); | 938 HValue* value = hydrogen_env->values()->at(i); |
| 899 LOperand* op = NULL; | 939 LOperand* op = NULL; |
| 900 if (value->IsArgumentsObject()) { | 940 if (value->IsArgumentsObject()) { |
| 901 op = NULL; | 941 op = NULL; |
| 902 } else if (value->IsPushArgument()) { | 942 } else if (value->IsPushArgument()) { |
| 903 op = new LArgument(argument_index++); | 943 op = new LArgument(argument_index++); |
| 904 } else { | 944 } else { |
| 905 op = UseOrConstant(value); | 945 op = UseAny(value); |
| 906 if (op->IsUnallocated()) { | |
| 907 LUnallocated* unalloc = LUnallocated::cast(op); | |
| 908 unalloc->set_policy(LUnallocated::ANY); | |
| 909 } | |
| 910 } | 946 } |
| 911 result->AddValue(op, value->representation()); | 947 result->AddValue(op, value->representation()); |
| 912 } | 948 } |
| 913 | 949 |
| 914 return result; | 950 return result; |
| 915 } | 951 } |
| 916 | 952 |
| 917 | 953 |
| 918 LInstruction* LChunkBuilder::DoGoto(HGoto* instr) { | 954 LInstruction* LChunkBuilder::DoGoto(HGoto* instr) { |
| 919 LInstruction* result = new LGoto(instr->FirstSuccessor()->block_id(), | 955 LInstruction* result = new LGoto(instr->FirstSuccessor()->block_id(), |
| 920 instr->include_stack_check()); | 956 instr->include_stack_check()); |
| 921 if (instr->include_stack_check()) result = AssignPointerMap(result); | 957 if (instr->include_stack_check()) result = AssignPointerMap(result); |
| 922 return result; | 958 return result; |
| 923 } | 959 } |
| 924 | 960 |
| 925 | 961 |
| 926 LInstruction* LChunkBuilder::DoBranch(HBranch* instr) { | 962 LInstruction* LChunkBuilder::DoTest(HTest* instr) { |
| 927 HValue* v = instr->value(); | 963 HValue* v = instr->value(); |
| 928 HBasicBlock* first = instr->FirstSuccessor(); | |
| 929 HBasicBlock* second = instr->SecondSuccessor(); | |
| 930 ASSERT(first != NULL && second != NULL); | |
| 931 int first_id = first->block_id(); | |
| 932 int second_id = second->block_id(); | |
| 933 | |
| 934 if (v->EmitAtUses()) { | 964 if (v->EmitAtUses()) { |
| 935 if (v->IsClassOfTest()) { | 965 if (v->IsClassOfTest()) { |
| 936 HClassOfTest* compare = HClassOfTest::cast(v); | 966 HClassOfTest* compare = HClassOfTest::cast(v); |
| 937 ASSERT(compare->value()->representation().IsTagged()); | 967 ASSERT(compare->value()->representation().IsTagged()); |
| 938 | 968 |
| 939 return new LClassOfTestAndBranch(UseTempRegister(compare->value()), | 969 return new LClassOfTestAndBranch(UseTempRegister(compare->value()), |
| 940 TempRegister(), | 970 TempRegister()); |
| 941 first_id, | |
| 942 second_id); | |
| 943 } else if (v->IsCompare()) { | 971 } else if (v->IsCompare()) { |
| 944 HCompare* compare = HCompare::cast(v); | 972 HCompare* compare = HCompare::cast(v); |
| 945 Token::Value op = compare->token(); | 973 Token::Value op = compare->token(); |
| 946 HValue* left = compare->left(); | 974 HValue* left = compare->left(); |
| 947 HValue* right = compare->right(); | 975 HValue* right = compare->right(); |
| 948 Representation r = compare->GetInputRepresentation(); | 976 Representation r = compare->GetInputRepresentation(); |
| 949 if (r.IsInteger32()) { | 977 if (r.IsInteger32()) { |
| 950 ASSERT(left->representation().IsInteger32()); | 978 ASSERT(left->representation().IsInteger32()); |
| 951 ASSERT(right->representation().IsInteger32()); | 979 ASSERT(right->representation().IsInteger32()); |
| 952 return new LCmpIDAndBranch(UseRegisterAtStart(left), | 980 return new LCmpIDAndBranch(UseRegisterAtStart(left), |
| 953 UseOrConstantAtStart(right), | 981 UseOrConstantAtStart(right)); |
| 954 first_id, | |
| 955 second_id); | |
| 956 } else if (r.IsDouble()) { | 982 } else if (r.IsDouble()) { |
| 957 ASSERT(left->representation().IsDouble()); | 983 ASSERT(left->representation().IsDouble()); |
| 958 ASSERT(right->representation().IsDouble()); | 984 ASSERT(right->representation().IsDouble()); |
| 959 return new LCmpIDAndBranch(UseRegisterAtStart(left), | 985 return new LCmpIDAndBranch(UseRegisterAtStart(left), |
| 960 UseRegisterAtStart(right), | 986 UseRegisterAtStart(right)); |
| 961 first_id, | |
| 962 second_id); | |
| 963 } else { | 987 } else { |
| 964 ASSERT(left->representation().IsTagged()); | 988 ASSERT(left->representation().IsTagged()); |
| 965 ASSERT(right->representation().IsTagged()); | 989 ASSERT(right->representation().IsTagged()); |
| 966 bool reversed = op == Token::GT || op == Token::LTE; | 990 bool reversed = op == Token::GT || op == Token::LTE; |
| 967 LOperand* left_operand = UseFixed(left, reversed ? r0 : r1); | 991 LOperand* left_operand = UseFixed(left, reversed ? r0 : r1); |
| 968 LOperand* right_operand = UseFixed(right, reversed ? r1 : r0); | 992 LOperand* right_operand = UseFixed(right, reversed ? r1 : r0); |
| 969 LInstruction* result = new LCmpTAndBranch(left_operand, | 993 LInstruction* result = new LCmpTAndBranch(left_operand, |
| 970 right_operand, | 994 right_operand); |
| 971 first_id, | |
| 972 second_id); | |
| 973 return MarkAsCall(result, instr); | 995 return MarkAsCall(result, instr); |
| 974 } | 996 } |
| 975 } else if (v->IsIsSmi()) { | 997 } else if (v->IsIsSmi()) { |
| 976 HIsSmi* compare = HIsSmi::cast(v); | 998 HIsSmi* compare = HIsSmi::cast(v); |
| 977 ASSERT(compare->value()->representation().IsTagged()); | 999 ASSERT(compare->value()->representation().IsTagged()); |
| 978 | 1000 |
| 979 return new LIsSmiAndBranch(Use(compare->value()), | 1001 return new LIsSmiAndBranch(Use(compare->value())); |
| 980 first_id, | |
| 981 second_id); | |
| 982 } else if (v->IsHasInstanceType()) { | 1002 } else if (v->IsHasInstanceType()) { |
| 983 HHasInstanceType* compare = HHasInstanceType::cast(v); | 1003 HHasInstanceType* compare = HHasInstanceType::cast(v); |
| 984 ASSERT(compare->value()->representation().IsTagged()); | 1004 ASSERT(compare->value()->representation().IsTagged()); |
| 985 | 1005 return new LHasInstanceTypeAndBranch( |
| 986 return new LHasInstanceTypeAndBranch(UseRegisterAtStart(compare->value()), | 1006 UseRegisterAtStart(compare->value())); |
| 987 first_id, | |
| 988 second_id); | |
| 989 } else if (v->IsHasCachedArrayIndex()) { | 1007 } else if (v->IsHasCachedArrayIndex()) { |
| 990 HHasCachedArrayIndex* compare = HHasCachedArrayIndex::cast(v); | 1008 HHasCachedArrayIndex* compare = HHasCachedArrayIndex::cast(v); |
| 991 ASSERT(compare->value()->representation().IsTagged()); | 1009 ASSERT(compare->value()->representation().IsTagged()); |
| 992 | 1010 |
| 993 return new LHasCachedArrayIndexAndBranch( | 1011 return new LHasCachedArrayIndexAndBranch( |
| 994 UseRegisterAtStart(compare->value()), first_id, second_id); | 1012 UseRegisterAtStart(compare->value())); |
| 995 } else if (v->IsIsNull()) { | 1013 } else if (v->IsIsNull()) { |
| 996 HIsNull* compare = HIsNull::cast(v); | 1014 HIsNull* compare = HIsNull::cast(v); |
| 997 ASSERT(compare->value()->representation().IsTagged()); | 1015 ASSERT(compare->value()->representation().IsTagged()); |
| 998 | 1016 |
| 999 return new LIsNullAndBranch(UseRegisterAtStart(compare->value()), | 1017 return new LIsNullAndBranch(UseRegisterAtStart(compare->value())); |
| 1000 first_id, | |
| 1001 second_id); | |
| 1002 } else if (v->IsIsObject()) { | 1018 } else if (v->IsIsObject()) { |
| 1003 HIsObject* compare = HIsObject::cast(v); | 1019 HIsObject* compare = HIsObject::cast(v); |
| 1004 ASSERT(compare->value()->representation().IsTagged()); | 1020 ASSERT(compare->value()->representation().IsTagged()); |
| 1005 | 1021 |
| 1006 LOperand* temp1 = TempRegister(); | 1022 LOperand* temp = TempRegister(); |
| 1007 LOperand* temp2 = TempRegister(); | 1023 return new LIsObjectAndBranch(UseRegisterAtStart(compare->value()), temp); |
| 1008 return new LIsObjectAndBranch(UseRegisterAtStart(compare->value()), | |
| 1009 temp1, | |
| 1010 temp2, | |
| 1011 first_id, | |
| 1012 second_id); | |
| 1013 } else if (v->IsCompareJSObjectEq()) { | 1024 } else if (v->IsCompareJSObjectEq()) { |
| 1014 HCompareJSObjectEq* compare = HCompareJSObjectEq::cast(v); | 1025 HCompareJSObjectEq* compare = HCompareJSObjectEq::cast(v); |
| 1015 return new LCmpJSObjectEqAndBranch(UseRegisterAtStart(compare->left()), | 1026 return new LCmpJSObjectEqAndBranch(UseRegisterAtStart(compare->left()), |
| 1016 UseRegisterAtStart(compare->right()), | 1027 UseRegisterAtStart(compare->right())); |
| 1017 first_id, | |
| 1018 second_id); | |
| 1019 } else if (v->IsInstanceOf()) { | 1028 } else if (v->IsInstanceOf()) { |
| 1020 HInstanceOf* instance_of = HInstanceOf::cast(v); | 1029 HInstanceOf* instance_of = HInstanceOf::cast(v); |
| 1021 LInstruction* result = | 1030 LInstruction* result = |
| 1022 new LInstanceOfAndBranch(Use(instance_of->left()), | 1031 new LInstanceOfAndBranch(Use(instance_of->left()), |
| 1023 Use(instance_of->right()), | 1032 Use(instance_of->right())); |
| 1024 first_id, | |
| 1025 second_id); | |
| 1026 return MarkAsCall(result, instr); | 1033 return MarkAsCall(result, instr); |
| 1027 } else if (v->IsTypeofIs()) { | 1034 } else if (v->IsTypeofIs()) { |
| 1028 HTypeofIs* typeof_is = HTypeofIs::cast(v); | 1035 HTypeofIs* typeof_is = HTypeofIs::cast(v); |
| 1029 return new LTypeofIsAndBranch(UseTempRegister(typeof_is->value()), | 1036 return new LTypeofIsAndBranch(UseTempRegister(typeof_is->value())); |
| 1030 first_id, | |
| 1031 second_id); | |
| 1032 } else { | 1037 } else { |
| 1033 if (v->IsConstant()) { | 1038 if (v->IsConstant()) { |
| 1034 if (HConstant::cast(v)->handle()->IsTrue()) { | 1039 if (HConstant::cast(v)->handle()->IsTrue()) { |
| 1035 return new LGoto(first_id); | 1040 return new LGoto(instr->FirstSuccessor()->block_id()); |
| 1036 } else if (HConstant::cast(v)->handle()->IsFalse()) { | 1041 } else if (HConstant::cast(v)->handle()->IsFalse()) { |
| 1037 return new LGoto(second_id); | 1042 return new LGoto(instr->SecondSuccessor()->block_id()); |
| 1038 } | 1043 } |
| 1039 } | 1044 } |
| 1040 Abort("Undefined compare before branch"); | 1045 Abort("Undefined compare before branch"); |
| 1041 return NULL; | 1046 return NULL; |
| 1042 } | 1047 } |
| 1043 } | 1048 } |
| 1044 return new LBranch(UseRegisterAtStart(v), first_id, second_id); | 1049 return new LBranch(UseRegisterAtStart(v)); |
| 1045 } | 1050 } |
| 1046 | 1051 |
| 1047 | 1052 |
| 1048 LInstruction* LChunkBuilder::DoCompareMapAndBranch( | 1053 LInstruction* LChunkBuilder::DoCompareMap(HCompareMap* instr) { |
| 1049 HCompareMapAndBranch* instr) { | |
| 1050 ASSERT(instr->value()->representation().IsTagged()); | 1054 ASSERT(instr->value()->representation().IsTagged()); |
| 1051 LOperand* value = UseRegisterAtStart(instr->value()); | 1055 LOperand* value = UseRegisterAtStart(instr->value()); |
| 1052 LOperand* temp = TempRegister(); | 1056 LOperand* temp = TempRegister(); |
| 1053 return new LCmpMapAndBranch(value, temp); | 1057 return new LCmpMapAndBranch(value, temp); |
| 1054 } | 1058 } |
| 1055 | 1059 |
| 1056 | 1060 |
| 1057 LInstruction* LChunkBuilder::DoArgumentsLength(HArgumentsLength* length) { | 1061 LInstruction* LChunkBuilder::DoArgumentsLength(HArgumentsLength* length) { |
| 1058 return DefineAsRegister(new LArgumentsLength(UseRegister(length->value()))); | 1062 return DefineAsRegister(new LArgumentsLength(UseRegister(length->value()))); |
| 1059 } | 1063 } |
| 1060 | 1064 |
| 1061 | 1065 |
| 1062 LInstruction* LChunkBuilder::DoArgumentsElements(HArgumentsElements* elems) { | 1066 LInstruction* LChunkBuilder::DoArgumentsElements(HArgumentsElements* elems) { |
| 1063 return DefineAsRegister(new LArgumentsElements); | 1067 return DefineAsRegister(new LArgumentsElements); |
| 1064 } | 1068 } |
| 1065 | 1069 |
| 1066 | 1070 |
| 1067 LInstruction* LChunkBuilder::DoInstanceOf(HInstanceOf* instr) { | 1071 LInstruction* LChunkBuilder::DoInstanceOf(HInstanceOf* instr) { |
| 1068 LInstruction* result = | 1072 LInstanceOf* result = |
| 1069 new LInstanceOf(UseFixed(instr->left(), r0), | 1073 new LInstanceOf(UseFixed(instr->left(), r0), |
| 1070 UseFixed(instr->right(), r1)); | 1074 UseFixed(instr->right(), r1)); |
| 1071 return MarkAsCall(DefineFixed(result, r0), instr); | 1075 return MarkAsCall(DefineFixed(result, r0), instr); |
| 1072 } | 1076 } |
| 1073 | 1077 |
| 1074 | 1078 |
| 1075 LInstruction* LChunkBuilder::DoInstanceOfKnownGlobal( | 1079 LInstruction* LChunkBuilder::DoInstanceOfKnownGlobal( |
| 1076 HInstanceOfKnownGlobal* instr) { | 1080 HInstanceOfKnownGlobal* instr) { |
| 1077 LInstruction* result = | 1081 LInstanceOfKnownGlobal* result = |
| 1078 new LInstanceOfKnownGlobal(UseFixed(instr->value(), r0)); | 1082 new LInstanceOfKnownGlobal(UseFixed(instr->value(), r0), FixedTemp(r4)); |
| 1079 return MarkAsCall(DefineFixed(result, r0), instr); | 1083 MarkAsSaveDoubles(result); |
| 1084 return AssignEnvironment(AssignPointerMap(DefineFixed(result, r0))); |
| 1080 } | 1085 } |
| 1081 | 1086 |
| 1082 | 1087 |
| 1083 LInstruction* LChunkBuilder::DoApplyArguments(HApplyArguments* instr) { | 1088 LInstruction* LChunkBuilder::DoApplyArguments(HApplyArguments* instr) { |
| 1084 LOperand* function = UseFixed(instr->function(), r1); | 1089 LOperand* function = UseFixed(instr->function(), r1); |
| 1085 LOperand* receiver = UseFixed(instr->receiver(), r0); | 1090 LOperand* receiver = UseFixed(instr->receiver(), r0); |
| 1086 LOperand* length = UseRegisterAtStart(instr->length()); | 1091 LOperand* length = UseRegisterAtStart(instr->length()); |
| 1087 LOperand* elements = UseRegisterAtStart(instr->elements()); | 1092 LOperand* elements = UseRegisterAtStart(instr->elements()); |
| 1088 LInstruction* result = new LApplyArguments(function, | 1093 LApplyArguments* result = new LApplyArguments(function, |
| 1089 receiver, | 1094 receiver, |
| 1090 length, | 1095 length, |
| 1091 elements); | 1096 elements); |
| 1092 return MarkAsCall(DefineFixed(result, r0), instr, CAN_DEOPTIMIZE_EAGERLY); | 1097 return MarkAsCall(DefineFixed(result, r0), instr, CAN_DEOPTIMIZE_EAGERLY); |
| 1093 } | 1098 } |
| 1094 | 1099 |
| 1095 | 1100 |
| 1096 LInstruction* LChunkBuilder::DoPushArgument(HPushArgument* instr) { | 1101 LInstruction* LChunkBuilder::DoPushArgument(HPushArgument* instr) { |
| 1097 ++argument_count_; | 1102 ++argument_count_; |
| 1098 LOperand* argument = Use(instr->argument()); | 1103 LOperand* argument = Use(instr->argument()); |
| 1099 return new LPushArgument(argument); | 1104 return new LPushArgument(argument); |
| 1100 } | 1105 } |
| 1101 | 1106 |
| (...skipping 12 matching lines...) Expand all Loading... |
| 1114 HCallConstantFunction* instr) { | 1119 HCallConstantFunction* instr) { |
| 1115 argument_count_ -= instr->argument_count(); | 1120 argument_count_ -= instr->argument_count(); |
| 1116 return MarkAsCall(DefineFixed(new LCallConstantFunction, r0), instr); | 1121 return MarkAsCall(DefineFixed(new LCallConstantFunction, r0), instr); |
| 1117 } | 1122 } |
| 1118 | 1123 |
| 1119 | 1124 |
| 1120 LInstruction* LChunkBuilder::DoUnaryMathOperation(HUnaryMathOperation* instr) { | 1125 LInstruction* LChunkBuilder::DoUnaryMathOperation(HUnaryMathOperation* instr) { |
| 1121 BuiltinFunctionId op = instr->op(); | 1126 BuiltinFunctionId op = instr->op(); |
| 1122 LOperand* input = UseRegisterAtStart(instr->value()); | 1127 LOperand* input = UseRegisterAtStart(instr->value()); |
| 1123 LOperand* temp = (op == kMathFloor) ? TempRegister() : NULL; | 1128 LOperand* temp = (op == kMathFloor) ? TempRegister() : NULL; |
| 1124 LInstruction* result = new LUnaryMathOperation(input, temp); | 1129 LUnaryMathOperation* result = new LUnaryMathOperation(input, temp); |
| 1125 switch (op) { | 1130 switch (op) { |
| 1126 case kMathAbs: | 1131 case kMathAbs: |
| 1127 return AssignEnvironment(AssignPointerMap(DefineSameAsFirst(result))); | 1132 return AssignEnvironment(AssignPointerMap(DefineSameAsFirst(result))); |
| 1128 case kMathFloor: | 1133 case kMathFloor: |
| 1129 return AssignEnvironment(DefineAsRegister(result)); | 1134 return AssignEnvironment(AssignPointerMap(DefineAsRegister(result))); |
| 1130 case kMathSqrt: | 1135 case kMathSqrt: |
| 1131 return DefineSameAsFirst(result); | 1136 return DefineSameAsFirst(result); |
| 1132 case kMathRound: | 1137 case kMathRound: |
| 1133 Abort("MathRound LUnaryMathOperation not implemented"); | 1138 Abort("MathRound LUnaryMathOperation not implemented"); |
| 1134 return NULL; | 1139 return NULL; |
| 1135 case kMathPowHalf: | 1140 case kMathPowHalf: |
| 1136 Abort("MathPowHalf LUnaryMathOperation not implemented"); | 1141 Abort("MathPowHalf LUnaryMathOperation not implemented"); |
| 1137 return NULL; | 1142 return NULL; |
| 1138 case kMathLog: | 1143 case kMathLog: |
| 1139 Abort("MathLog LUnaryMathOperation not implemented"); | 1144 Abort("MathLog LUnaryMathOperation not implemented"); |
| 1140 return NULL; | 1145 return NULL; |
| 1141 case kMathCos: | 1146 case kMathCos: |
| 1142 Abort("MathCos LUnaryMathOperation not implemented"); | 1147 Abort("MathCos LUnaryMathOperation not implemented"); |
| 1143 return NULL; | 1148 return NULL; |
| 1144 case kMathSin: | 1149 case kMathSin: |
| 1145 Abort("MathSin LUnaryMathOperation not implemented"); | 1150 Abort("MathSin LUnaryMathOperation not implemented"); |
| 1146 return NULL; | 1151 return NULL; |
| 1147 default: | 1152 default: |
| 1148 UNREACHABLE(); | 1153 UNREACHABLE(); |
| 1149 return NULL; | 1154 return NULL; |
| 1150 } | 1155 } |
| 1151 } | 1156 } |
| 1152 | 1157 |
| 1153 | 1158 |
| 1154 LInstruction* LChunkBuilder::DoCallKeyed(HCallKeyed* instr) { | 1159 LInstruction* LChunkBuilder::DoCallKeyed(HCallKeyed* instr) { |
| 1155 ASSERT(instr->key()->representation().IsTagged()); | 1160 ASSERT(instr->key()->representation().IsTagged()); |
| 1156 argument_count_ -= instr->argument_count(); | 1161 argument_count_ -= instr->argument_count(); |
| 1157 UseFixed(instr->key(), r2); | 1162 LOperand* key = UseFixed(instr->key(), r2); |
| 1158 return MarkAsCall(DefineFixed(new LCallKeyed, r0), instr); | 1163 return MarkAsCall(DefineFixed(new LCallKeyed(key), r0), instr); |
| 1159 } | 1164 } |
| 1160 | 1165 |
| 1161 | 1166 |
| 1162 LInstruction* LChunkBuilder::DoCallNamed(HCallNamed* instr) { | 1167 LInstruction* LChunkBuilder::DoCallNamed(HCallNamed* instr) { |
| 1163 argument_count_ -= instr->argument_count(); | 1168 argument_count_ -= instr->argument_count(); |
| 1164 return MarkAsCall(DefineFixed(new LCallNamed, r0), instr); | 1169 return MarkAsCall(DefineFixed(new LCallNamed, r0), instr); |
| 1165 } | 1170 } |
| 1166 | 1171 |
| 1167 | 1172 |
| 1168 LInstruction* LChunkBuilder::DoCallGlobal(HCallGlobal* instr) { | 1173 LInstruction* LChunkBuilder::DoCallGlobal(HCallGlobal* instr) { |
| 1169 argument_count_ -= instr->argument_count(); | 1174 argument_count_ -= instr->argument_count(); |
| 1170 return MarkAsCall(DefineFixed(new LCallGlobal, r0), instr); | 1175 return MarkAsCall(DefineFixed(new LCallGlobal, r0), instr); |
| 1171 } | 1176 } |
| 1172 | 1177 |
| 1173 | 1178 |
| 1174 LInstruction* LChunkBuilder::DoCallKnownGlobal(HCallKnownGlobal* instr) { | 1179 LInstruction* LChunkBuilder::DoCallKnownGlobal(HCallKnownGlobal* instr) { |
| 1175 argument_count_ -= instr->argument_count(); | 1180 argument_count_ -= instr->argument_count(); |
| 1176 return MarkAsCall(DefineFixed(new LCallKnownGlobal, r0), instr); | 1181 return MarkAsCall(DefineFixed(new LCallKnownGlobal, r0), instr); |
| 1177 } | 1182 } |
| 1178 | 1183 |
| 1179 | 1184 |
| 1180 LInstruction* LChunkBuilder::DoCallNew(HCallNew* instr) { | 1185 LInstruction* LChunkBuilder::DoCallNew(HCallNew* instr) { |
| 1181 LOperand* constructor = UseFixed(instr->constructor(), r1); | 1186 LOperand* constructor = UseFixed(instr->constructor(), r1); |
| 1182 argument_count_ -= instr->argument_count(); | 1187 argument_count_ -= instr->argument_count(); |
| 1183 LInstruction* result = new LCallNew(constructor); | 1188 LCallNew* result = new LCallNew(constructor); |
| 1184 return MarkAsCall(DefineFixed(result, r0), instr); | 1189 return MarkAsCall(DefineFixed(result, r0), instr); |
| 1185 } | 1190 } |
| 1186 | 1191 |
| 1187 | 1192 |
| 1188 LInstruction* LChunkBuilder::DoCallFunction(HCallFunction* instr) { | 1193 LInstruction* LChunkBuilder::DoCallFunction(HCallFunction* instr) { |
| 1189 argument_count_ -= instr->argument_count(); | 1194 argument_count_ -= instr->argument_count(); |
| 1190 return MarkAsCall(DefineFixed(new LCallFunction, r0), instr); | 1195 return MarkAsCall(DefineFixed(new LCallFunction, r0), instr); |
| 1191 } | 1196 } |
| 1192 | 1197 |
| 1193 | 1198 |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1231 | 1236 |
| 1232 LInstruction* LChunkBuilder::DoBitXor(HBitXor* instr) { | 1237 LInstruction* LChunkBuilder::DoBitXor(HBitXor* instr) { |
| 1233 return DoBit(Token::BIT_XOR, instr); | 1238 return DoBit(Token::BIT_XOR, instr); |
| 1234 } | 1239 } |
| 1235 | 1240 |
| 1236 | 1241 |
| 1237 LInstruction* LChunkBuilder::DoDiv(HDiv* instr) { | 1242 LInstruction* LChunkBuilder::DoDiv(HDiv* instr) { |
| 1238 if (instr->representation().IsDouble()) { | 1243 if (instr->representation().IsDouble()) { |
| 1239 return DoArithmeticD(Token::DIV, instr); | 1244 return DoArithmeticD(Token::DIV, instr); |
| 1240 } else if (instr->representation().IsInteger32()) { | 1245 } else if (instr->representation().IsInteger32()) { |
| 1241 // The temporary operand is necessary to ensure that right is not allocated | 1246 // TODO(1042) The fixed register allocation |
| 1242 // into edx. | 1247 // is needed because we call GenericBinaryOpStub from |
| 1243 FixedTemp(r1); | 1248 // the generated code, which requires registers r0 |
| 1249 // and r1 to be used. We should remove that |
| 1250 // when we provide a native implementation. |
| 1244 LOperand* value = UseFixed(instr->left(), r0); | 1251 LOperand* value = UseFixed(instr->left(), r0); |
| 1245 LOperand* divisor = UseRegister(instr->right()); | 1252 LOperand* divisor = UseFixed(instr->right(), r1); |
| 1246 return AssignEnvironment(DefineFixed(new LDivI(value, divisor), r0)); | 1253 return AssignEnvironment(AssignPointerMap( |
| 1254 DefineFixed(new LDivI(value, divisor), r0))); |
| 1247 } else { | 1255 } else { |
| 1248 return DoArithmeticT(Token::DIV, instr); | 1256 return DoArithmeticT(Token::DIV, instr); |
| 1249 } | 1257 } |
| 1250 } | 1258 } |
| 1251 | 1259 |
| 1252 | 1260 |
| 1253 LInstruction* LChunkBuilder::DoMod(HMod* instr) { | 1261 LInstruction* LChunkBuilder::DoMod(HMod* instr) { |
| 1254 if (instr->representation().IsInteger32()) { | 1262 if (instr->representation().IsInteger32()) { |
| 1263 // TODO(1042) The fixed register allocation |
| 1264 // is needed because we call GenericBinaryOpStub from |
| 1265 // the generated code, which requires registers r0 |
| 1266 // and r1 to be used. We should remove that |
| 1267 // when we provide a native implementation. |
| 1255 ASSERT(instr->left()->representation().IsInteger32()); | 1268 ASSERT(instr->left()->representation().IsInteger32()); |
| 1256 ASSERT(instr->right()->representation().IsInteger32()); | 1269 ASSERT(instr->right()->representation().IsInteger32()); |
| 1257 // The temporary operand is necessary to ensure that right is not allocated | |
| 1258 // into edx. | |
| 1259 FixedTemp(r1); | |
| 1260 LOperand* value = UseFixed(instr->left(), r0); | 1270 LOperand* value = UseFixed(instr->left(), r0); |
| 1261 LOperand* divisor = UseRegister(instr->right()); | 1271 LOperand* divisor = UseFixed(instr->right(), r1); |
| 1262 LInstruction* result = DefineFixed(new LModI(value, divisor), r1); | 1272 LInstruction* result = DefineFixed(new LModI(value, divisor), r0); |
| 1263 if (instr->CheckFlag(HValue::kBailoutOnMinusZero) || | 1273 result = AssignEnvironment(AssignPointerMap(result)); |
| 1264 instr->CheckFlag(HValue::kCanBeDivByZero)) { | |
| 1265 result = AssignEnvironment(result); | |
| 1266 } | |
| 1267 return result; | 1274 return result; |
| 1268 } else if (instr->representation().IsTagged()) { | 1275 } else if (instr->representation().IsTagged()) { |
| 1269 return DoArithmeticT(Token::MOD, instr); | 1276 return DoArithmeticT(Token::MOD, instr); |
| 1270 } else { | 1277 } else { |
| 1271 ASSERT(instr->representation().IsDouble()); | 1278 ASSERT(instr->representation().IsDouble()); |
| 1272 // We call a C function for double modulo. It can't trigger a GC. | 1279 // We call a C function for double modulo. It can't trigger a GC. |
| 1273 // We need to use fixed result register for the call. | 1280 // We need to use fixed result register for the call. |
| 1274 // TODO(fschneider): Allow any register as input registers. | 1281 // TODO(fschneider): Allow any register as input registers. |
| 1275 LOperand* left = UseFixedDouble(instr->left(), d1); | 1282 LOperand* left = UseFixedDouble(instr->left(), d1); |
| 1276 LOperand* right = UseFixedDouble(instr->right(), d2); | 1283 LOperand* right = UseFixedDouble(instr->right(), d2); |
| (...skipping 20 matching lines...) Expand all Loading... |
| 1297 } else { | 1304 } else { |
| 1298 return DoArithmeticT(Token::MUL, instr); | 1305 return DoArithmeticT(Token::MUL, instr); |
| 1299 } | 1306 } |
| 1300 } | 1307 } |
| 1301 | 1308 |
| 1302 | 1309 |
| 1303 LInstruction* LChunkBuilder::DoSub(HSub* instr) { | 1310 LInstruction* LChunkBuilder::DoSub(HSub* instr) { |
| 1304 if (instr->representation().IsInteger32()) { | 1311 if (instr->representation().IsInteger32()) { |
| 1305 ASSERT(instr->left()->representation().IsInteger32()); | 1312 ASSERT(instr->left()->representation().IsInteger32()); |
| 1306 ASSERT(instr->right()->representation().IsInteger32()); | 1313 ASSERT(instr->right()->representation().IsInteger32()); |
| 1307 LOperand* left = UseRegisterAtStart(instr->LeastConstantOperand()); | 1314 LOperand* left = UseRegisterAtStart(instr->left()); |
| 1308 LOperand* right = UseOrConstantAtStart(instr->MostConstantOperand()); | 1315 LOperand* right = UseOrConstantAtStart(instr->right()); |
| 1309 LSubI* sub = new LSubI(left, right); | 1316 LSubI* sub = new LSubI(left, right); |
| 1310 LInstruction* result = DefineSameAsFirst(sub); | 1317 LInstruction* result = DefineSameAsFirst(sub); |
| 1311 if (instr->CheckFlag(HValue::kCanOverflow)) { | 1318 if (instr->CheckFlag(HValue::kCanOverflow)) { |
| 1312 result = AssignEnvironment(result); | 1319 result = AssignEnvironment(result); |
| 1313 } | 1320 } |
| 1314 return result; | 1321 return result; |
| 1315 } else if (instr->representation().IsDouble()) { | 1322 } else if (instr->representation().IsDouble()) { |
| 1316 return DoArithmeticD(Token::SUB, instr); | 1323 return DoArithmeticD(Token::SUB, instr); |
| 1317 } else { | 1324 } else { |
| 1318 return DoArithmeticT(Token::SUB, instr); | 1325 return DoArithmeticT(Token::SUB, instr); |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1361 ASSERT(instr->right()->representation().IsDouble()); | 1368 ASSERT(instr->right()->representation().IsDouble()); |
| 1362 LOperand* left = UseRegisterAtStart(instr->left()); | 1369 LOperand* left = UseRegisterAtStart(instr->left()); |
| 1363 LOperand* right = UseRegisterAtStart(instr->right()); | 1370 LOperand* right = UseRegisterAtStart(instr->right()); |
| 1364 return DefineAsRegister(new LCmpID(left, right)); | 1371 return DefineAsRegister(new LCmpID(left, right)); |
| 1365 } else { | 1372 } else { |
| 1366 ASSERT(instr->left()->representation().IsTagged()); | 1373 ASSERT(instr->left()->representation().IsTagged()); |
| 1367 ASSERT(instr->right()->representation().IsTagged()); | 1374 ASSERT(instr->right()->representation().IsTagged()); |
| 1368 bool reversed = (op == Token::GT || op == Token::LTE); | 1375 bool reversed = (op == Token::GT || op == Token::LTE); |
| 1369 LOperand* left = UseFixed(instr->left(), reversed ? r0 : r1); | 1376 LOperand* left = UseFixed(instr->left(), reversed ? r0 : r1); |
| 1370 LOperand* right = UseFixed(instr->right(), reversed ? r1 : r0); | 1377 LOperand* right = UseFixed(instr->right(), reversed ? r1 : r0); |
| 1371 LInstruction* result = new LCmpT(left, right); | 1378 LCmpT* result = new LCmpT(left, right); |
| 1372 return MarkAsCall(DefineFixed(result, r0), instr); | 1379 return MarkAsCall(DefineFixed(result, r0), instr); |
| 1373 } | 1380 } |
| 1374 } | 1381 } |
| 1375 | 1382 |
| 1376 | 1383 |
| 1377 LInstruction* LChunkBuilder::DoCompareJSObjectEq( | 1384 LInstruction* LChunkBuilder::DoCompareJSObjectEq( |
| 1378 HCompareJSObjectEq* instr) { | 1385 HCompareJSObjectEq* instr) { |
| 1379 LOperand* left = UseRegisterAtStart(instr->left()); | 1386 LOperand* left = UseRegisterAtStart(instr->left()); |
| 1380 LOperand* right = UseRegisterAtStart(instr->right()); | 1387 LOperand* right = UseRegisterAtStart(instr->right()); |
| 1381 LInstruction* result = new LCmpJSObjectEq(left, right); | 1388 LCmpJSObjectEq* result = new LCmpJSObjectEq(left, right); |
| 1382 return DefineAsRegister(result); | 1389 return DefineAsRegister(result); |
| 1383 } | 1390 } |
| 1384 | 1391 |
| 1385 | 1392 |
| 1386 LInstruction* LChunkBuilder::DoIsNull(HIsNull* instr) { | 1393 LInstruction* LChunkBuilder::DoIsNull(HIsNull* instr) { |
| 1387 ASSERT(instr->value()->representation().IsTagged()); | 1394 ASSERT(instr->value()->representation().IsTagged()); |
| 1388 LOperand* value = UseRegisterAtStart(instr->value()); | 1395 LOperand* value = UseRegisterAtStart(instr->value()); |
| 1389 | 1396 |
| 1390 return DefineAsRegister(new LIsNull(value)); | 1397 return DefineAsRegister(new LIsNull(value)); |
| 1391 } | 1398 } |
| 1392 | 1399 |
| 1393 | 1400 |
| 1394 LInstruction* LChunkBuilder::DoIsObject(HIsObject* instr) { | 1401 LInstruction* LChunkBuilder::DoIsObject(HIsObject* instr) { |
| 1395 ASSERT(instr->value()->representation().IsTagged()); | 1402 ASSERT(instr->value()->representation().IsTagged()); |
| 1396 LOperand* value = UseRegisterAtStart(instr->value()); | 1403 LOperand* value = UseRegisterAtStart(instr->value()); |
| 1397 | 1404 |
| 1398 return DefineAsRegister(new LIsObject(value, TempRegister())); | 1405 return DefineAsRegister(new LIsObject(value)); |
| 1399 } | 1406 } |
| 1400 | 1407 |
| 1401 | 1408 |
| 1402 LInstruction* LChunkBuilder::DoIsSmi(HIsSmi* instr) { | 1409 LInstruction* LChunkBuilder::DoIsSmi(HIsSmi* instr) { |
| 1403 ASSERT(instr->value()->representation().IsTagged()); | 1410 ASSERT(instr->value()->representation().IsTagged()); |
| 1404 LOperand* value = UseAtStart(instr->value()); | 1411 LOperand* value = UseAtStart(instr->value()); |
| 1405 | 1412 |
| 1406 return DefineAsRegister(new LIsSmi(value)); | 1413 return DefineAsRegister(new LIsSmi(value)); |
| 1407 } | 1414 } |
| 1408 | 1415 |
| (...skipping 29 matching lines...) Expand all Loading... |
| 1438 | 1445 |
| 1439 | 1446 |
| 1440 LInstruction* LChunkBuilder::DoFixedArrayLength(HFixedArrayLength* instr) { | 1447 LInstruction* LChunkBuilder::DoFixedArrayLength(HFixedArrayLength* instr) { |
| 1441 LOperand* array = UseRegisterAtStart(instr->value()); | 1448 LOperand* array = UseRegisterAtStart(instr->value()); |
| 1442 return DefineAsRegister(new LFixedArrayLength(array)); | 1449 return DefineAsRegister(new LFixedArrayLength(array)); |
| 1443 } | 1450 } |
| 1444 | 1451 |
| 1445 | 1452 |
| 1446 LInstruction* LChunkBuilder::DoValueOf(HValueOf* instr) { | 1453 LInstruction* LChunkBuilder::DoValueOf(HValueOf* instr) { |
| 1447 LOperand* object = UseRegister(instr->value()); | 1454 LOperand* object = UseRegister(instr->value()); |
| 1448 LInstruction* result = new LValueOf(object, TempRegister()); | 1455 LValueOf* result = new LValueOf(object, TempRegister()); |
| 1449 return AssignEnvironment(DefineSameAsFirst(result)); | 1456 return AssignEnvironment(DefineSameAsFirst(result)); |
| 1450 } | 1457 } |
| 1451 | 1458 |
| 1452 | 1459 |
| 1453 LInstruction* LChunkBuilder::DoBoundsCheck(HBoundsCheck* instr) { | 1460 LInstruction* LChunkBuilder::DoBoundsCheck(HBoundsCheck* instr) { |
| 1454 return AssignEnvironment(new LBoundsCheck(UseRegisterAtStart(instr->index()), | 1461 return AssignEnvironment(new LBoundsCheck(UseRegisterAtStart(instr->index()), |
| 1455 UseRegister(instr->length()))); | 1462 UseRegister(instr->length()))); |
| 1456 } | 1463 } |
| 1457 | 1464 |
| 1458 | 1465 |
| 1459 LInstruction* LChunkBuilder::DoThrow(HThrow* instr) { | 1466 LInstruction* LChunkBuilder::DoThrow(HThrow* instr) { |
| 1460 LOperand* value = UseFixed(instr->value(), r0); | 1467 LOperand* value = UseFixed(instr->value(), r0); |
| 1461 return MarkAsCall(new LThrow(value), instr); | 1468 return MarkAsCall(new LThrow(value), instr); |
| 1462 } | 1469 } |
| 1463 | 1470 |
| 1464 | 1471 |
| 1465 LInstruction* LChunkBuilder::DoChange(HChange* instr) { | 1472 LInstruction* LChunkBuilder::DoChange(HChange* instr) { |
| 1466 Representation from = instr->from(); | 1473 Representation from = instr->from(); |
| 1467 Representation to = instr->to(); | 1474 Representation to = instr->to(); |
| 1468 if (from.IsTagged()) { | 1475 if (from.IsTagged()) { |
| 1469 if (to.IsDouble()) { | 1476 if (to.IsDouble()) { |
| 1470 LOperand* value = UseRegister(instr->value()); | 1477 LOperand* value = UseRegister(instr->value()); |
| 1471 LInstruction* res = new LNumberUntagD(value); | 1478 LNumberUntagD* res = new LNumberUntagD(value); |
| 1472 return AssignEnvironment(DefineAsRegister(res)); | 1479 return AssignEnvironment(DefineAsRegister(res)); |
| 1473 } else { | 1480 } else { |
| 1474 ASSERT(to.IsInteger32()); | 1481 ASSERT(to.IsInteger32()); |
| 1475 LOperand* value = UseRegister(instr->value()); | 1482 LOperand* value = UseRegister(instr->value()); |
| 1476 bool needs_check = !instr->value()->type().IsSmi(); | 1483 bool needs_check = !instr->value()->type().IsSmi(); |
| 1477 LInstruction* res = NULL; | 1484 LInstruction* res = NULL; |
| 1478 if (needs_check) { | 1485 if (needs_check) { |
| 1479 res = DefineSameAsFirst(new LTaggedToI(value, FixedTemp(d1))); | 1486 res = DefineSameAsFirst(new LTaggedToI(value, FixedTemp(d1))); |
| 1480 } else { | 1487 } else { |
| 1481 res = DefineSameAsFirst(new LSmiUntag(value, needs_check)); | 1488 res = DefineSameAsFirst(new LSmiUntag(value, needs_check)); |
| 1482 } | 1489 } |
| 1483 if (needs_check) { | 1490 if (needs_check) { |
| 1484 res = AssignEnvironment(res); | 1491 res = AssignEnvironment(res); |
| 1485 } | 1492 } |
| 1486 return res; | 1493 return res; |
| 1487 } | 1494 } |
| 1488 } else if (from.IsDouble()) { | 1495 } else if (from.IsDouble()) { |
| 1489 if (to.IsTagged()) { | 1496 if (to.IsTagged()) { |
| 1490 LOperand* value = UseRegister(instr->value()); | 1497 LOperand* value = UseRegister(instr->value()); |
| 1491 LOperand* temp1 = TempRegister(); | 1498 LOperand* temp1 = TempRegister(); |
| 1492 LOperand* temp2 = TempRegister(); | 1499 LOperand* temp2 = TempRegister(); |
| 1493 | 1500 |
| 1494 // Make sure that the temp and result_temp registers are | 1501 // Make sure that the temp and result_temp registers are |
| 1495 // different. | 1502 // different. |
| 1496 LUnallocated* result_temp = TempRegister(); | 1503 LUnallocated* result_temp = TempRegister(); |
| 1497 LInstruction* result = new LNumberTagD(value, temp1, temp2); | 1504 LNumberTagD* result = new LNumberTagD(value, temp1, temp2); |
| 1498 Define(result, result_temp); | 1505 Define(result, result_temp); |
| 1499 return AssignPointerMap(result); | 1506 return AssignPointerMap(result); |
| 1500 } else { | 1507 } else { |
| 1501 ASSERT(to.IsInteger32()); | 1508 ASSERT(to.IsInteger32()); |
| 1502 LOperand* value = UseRegister(instr->value()); | 1509 LOperand* value = UseRegister(instr->value()); |
| 1503 LInstruction* res = new LDoubleToI(value); | 1510 LDoubleToI* res = new LDoubleToI(value); |
| 1504 return AssignEnvironment(DefineAsRegister(res)); | 1511 return AssignEnvironment(DefineAsRegister(res)); |
| 1505 } | 1512 } |
| 1506 } else if (from.IsInteger32()) { | 1513 } else if (from.IsInteger32()) { |
| 1507 if (to.IsTagged()) { | 1514 if (to.IsTagged()) { |
| 1508 HValue* val = instr->value(); | 1515 HValue* val = instr->value(); |
| 1509 LOperand* value = UseRegister(val); | 1516 LOperand* value = UseRegister(val); |
| 1510 if (val->HasRange() && val->range()->IsInSmiRange()) { | 1517 if (val->HasRange() && val->range()->IsInSmiRange()) { |
| 1511 return DefineSameAsFirst(new LSmiTag(value)); | 1518 return DefineSameAsFirst(new LSmiTag(value)); |
| 1512 } else { | 1519 } else { |
| 1513 LInstruction* result = new LNumberTagI(value); | 1520 LNumberTagI* result = new LNumberTagI(value); |
| 1514 return AssignEnvironment(AssignPointerMap(DefineSameAsFirst(result))); | 1521 return AssignEnvironment(AssignPointerMap(DefineSameAsFirst(result))); |
| 1515 } | 1522 } |
| 1516 } else { | 1523 } else { |
| 1517 ASSERT(to.IsDouble()); | 1524 ASSERT(to.IsDouble()); |
| 1518 LOperand* value = Use(instr->value()); | 1525 LOperand* value = Use(instr->value()); |
| 1519 return DefineAsRegister(new LInteger32ToDouble(value)); | 1526 return DefineAsRegister(new LInteger32ToDouble(value)); |
| 1520 } | 1527 } |
| 1521 } | 1528 } |
| 1522 UNREACHABLE(); | 1529 UNREACHABLE(); |
| 1523 return NULL; | 1530 return NULL; |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1573 Representation r = instr->representation(); | 1580 Representation r = instr->representation(); |
| 1574 if (r.IsInteger32()) { | 1581 if (r.IsInteger32()) { |
| 1575 int32_t value = instr->Integer32Value(); | 1582 int32_t value = instr->Integer32Value(); |
| 1576 return DefineAsRegister(new LConstantI(value)); | 1583 return DefineAsRegister(new LConstantI(value)); |
| 1577 } else if (r.IsDouble()) { | 1584 } else if (r.IsDouble()) { |
| 1578 double value = instr->DoubleValue(); | 1585 double value = instr->DoubleValue(); |
| 1579 return DefineAsRegister(new LConstantD(value)); | 1586 return DefineAsRegister(new LConstantD(value)); |
| 1580 } else if (r.IsTagged()) { | 1587 } else if (r.IsTagged()) { |
| 1581 return DefineAsRegister(new LConstantT(instr->handle())); | 1588 return DefineAsRegister(new LConstantT(instr->handle())); |
| 1582 } else { | 1589 } else { |
| 1583 Abort("unsupported constant of type double"); | 1590 UNREACHABLE(); |
| 1584 return NULL; | 1591 return NULL; |
| 1585 } | 1592 } |
| 1586 } | 1593 } |
| 1587 | 1594 |
| 1588 | 1595 |
| 1589 LInstruction* LChunkBuilder::DoLoadGlobal(HLoadGlobal* instr) { | 1596 LInstruction* LChunkBuilder::DoLoadGlobal(HLoadGlobal* instr) { |
| 1590 LInstruction* result = new LLoadGlobal(); | 1597 LLoadGlobal* result = new LLoadGlobal(); |
| 1591 return instr->check_hole_value() | 1598 return instr->check_hole_value() |
| 1592 ? AssignEnvironment(DefineAsRegister(result)) | 1599 ? AssignEnvironment(DefineAsRegister(result)) |
| 1593 : DefineAsRegister(result); | 1600 : DefineAsRegister(result); |
| 1594 } | 1601 } |
| 1595 | 1602 |
| 1596 | 1603 |
| 1597 LInstruction* LChunkBuilder::DoStoreGlobal(HStoreGlobal* instr) { | 1604 LInstruction* LChunkBuilder::DoStoreGlobal(HStoreGlobal* instr) { |
| 1598 return new LStoreGlobal(UseRegisterAtStart(instr->value())); | 1605 return new LStoreGlobal(UseRegisterAtStart(instr->value())); |
| 1599 } | 1606 } |
| 1600 | 1607 |
| 1601 | 1608 |
| 1609 LInstruction* LChunkBuilder::DoLoadContextSlot(HLoadContextSlot* instr) { |
| 1610 return DefineAsRegister(new LLoadContextSlot); |
| 1611 } |
| 1612 |
| 1613 |
| 1602 LInstruction* LChunkBuilder::DoLoadNamedField(HLoadNamedField* instr) { | 1614 LInstruction* LChunkBuilder::DoLoadNamedField(HLoadNamedField* instr) { |
| 1603 return DefineAsRegister( | 1615 return DefineAsRegister( |
| 1604 new LLoadNamedField(UseRegisterAtStart(instr->object()))); | 1616 new LLoadNamedField(UseRegisterAtStart(instr->object()))); |
| 1605 } | 1617 } |
| 1606 | 1618 |
| 1607 | 1619 |
| 1608 LInstruction* LChunkBuilder::DoLoadNamedGeneric(HLoadNamedGeneric* instr) { | 1620 LInstruction* LChunkBuilder::DoLoadNamedGeneric(HLoadNamedGeneric* instr) { |
| 1609 LOperand* object = UseFixed(instr->object(), r0); | 1621 LOperand* object = UseFixed(instr->object(), r0); |
| 1610 LInstruction* result = DefineFixed(new LLoadNamedGeneric(object), r0); | 1622 LInstruction* result = DefineFixed(new LLoadNamedGeneric(object), r0); |
| 1611 return MarkAsCall(result, instr); | 1623 return MarkAsCall(result, instr); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 1624 return DefineSameAsFirst(new LLoadElements(input)); | 1636 return DefineSameAsFirst(new LLoadElements(input)); |
| 1625 } | 1637 } |
| 1626 | 1638 |
| 1627 | 1639 |
| 1628 LInstruction* LChunkBuilder::DoLoadKeyedFastElement( | 1640 LInstruction* LChunkBuilder::DoLoadKeyedFastElement( |
| 1629 HLoadKeyedFastElement* instr) { | 1641 HLoadKeyedFastElement* instr) { |
| 1630 ASSERT(instr->representation().IsTagged()); | 1642 ASSERT(instr->representation().IsTagged()); |
| 1631 ASSERT(instr->key()->representation().IsInteger32()); | 1643 ASSERT(instr->key()->representation().IsInteger32()); |
| 1632 LOperand* obj = UseRegisterAtStart(instr->object()); | 1644 LOperand* obj = UseRegisterAtStart(instr->object()); |
| 1633 LOperand* key = UseRegisterAtStart(instr->key()); | 1645 LOperand* key = UseRegisterAtStart(instr->key()); |
| 1634 LInstruction* result = new LLoadKeyedFastElement(obj, key); | 1646 LLoadKeyedFastElement* result = new LLoadKeyedFastElement(obj, key); |
| 1635 return AssignEnvironment(DefineSameAsFirst(result)); | 1647 return AssignEnvironment(DefineSameAsFirst(result)); |
| 1636 } | 1648 } |
| 1637 | 1649 |
| 1638 | 1650 |
| 1639 LInstruction* LChunkBuilder::DoLoadKeyedGeneric(HLoadKeyedGeneric* instr) { | 1651 LInstruction* LChunkBuilder::DoLoadKeyedGeneric(HLoadKeyedGeneric* instr) { |
| 1640 LOperand* object = UseFixed(instr->object(), r1); | 1652 LOperand* object = UseFixed(instr->object(), r1); |
| 1641 LOperand* key = UseFixed(instr->key(), r0); | 1653 LOperand* key = UseFixed(instr->key(), r0); |
| 1642 | 1654 |
| 1643 LInstruction* result = | 1655 LInstruction* result = |
| 1644 DefineFixed(new LLoadKeyedGeneric(object, key), r0); | 1656 DefineFixed(new LLoadKeyedGeneric(object, key), r0); |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1695 | 1707 |
| 1696 LInstruction* LChunkBuilder::DoStoreNamedGeneric(HStoreNamedGeneric* instr) { | 1708 LInstruction* LChunkBuilder::DoStoreNamedGeneric(HStoreNamedGeneric* instr) { |
| 1697 LOperand* obj = UseFixed(instr->object(), r1); | 1709 LOperand* obj = UseFixed(instr->object(), r1); |
| 1698 LOperand* val = UseFixed(instr->value(), r0); | 1710 LOperand* val = UseFixed(instr->value(), r0); |
| 1699 | 1711 |
| 1700 LInstruction* result = new LStoreNamedGeneric(obj, val); | 1712 LInstruction* result = new LStoreNamedGeneric(obj, val); |
| 1701 return MarkAsCall(result, instr); | 1713 return MarkAsCall(result, instr); |
| 1702 } | 1714 } |
| 1703 | 1715 |
| 1704 | 1716 |
| 1717 LInstruction* LChunkBuilder::DoStringCharCodeAt(HStringCharCodeAt* instr) { |
| 1718 LOperand* string = UseRegister(instr->string()); |
| 1719 LOperand* index = UseRegisterOrConstant(instr->index()); |
| 1720 LStringCharCodeAt* result = new LStringCharCodeAt(string, index); |
| 1721 return AssignEnvironment(AssignPointerMap(DefineAsRegister(result))); |
| 1722 } |
| 1723 |
| 1724 |
| 1725 LInstruction* LChunkBuilder::DoStringLength(HStringLength* instr) { |
| 1726 LOperand* string = UseRegisterAtStart(instr->value()); |
| 1727 return DefineAsRegister(new LStringLength(string)); |
| 1728 } |
| 1729 |
| 1730 |
| 1705 LInstruction* LChunkBuilder::DoArrayLiteral(HArrayLiteral* instr) { | 1731 LInstruction* LChunkBuilder::DoArrayLiteral(HArrayLiteral* instr) { |
| 1706 return MarkAsCall(DefineFixed(new LArrayLiteral, r0), instr); | 1732 return MarkAsCall(DefineFixed(new LArrayLiteral, r0), instr); |
| 1707 } | 1733 } |
| 1708 | 1734 |
| 1709 | 1735 |
| 1710 LInstruction* LChunkBuilder::DoObjectLiteral(HObjectLiteral* instr) { | 1736 LInstruction* LChunkBuilder::DoObjectLiteral(HObjectLiteral* instr) { |
| 1711 return MarkAsCall(DefineFixed(new LObjectLiteral, r0), instr); | 1737 return MarkAsCall(DefineFixed(new LObjectLiteral, r0), instr); |
| 1712 } | 1738 } |
| 1713 | 1739 |
| 1714 | 1740 |
| 1715 LInstruction* LChunkBuilder::DoRegExpLiteral(HRegExpLiteral* instr) { | 1741 LInstruction* LChunkBuilder::DoRegExpLiteral(HRegExpLiteral* instr) { |
| 1716 return MarkAsCall(DefineFixed(new LRegExpLiteral, r0), instr); | 1742 return MarkAsCall(DefineFixed(new LRegExpLiteral, r0), instr); |
| 1717 } | 1743 } |
| 1718 | 1744 |
| 1719 | 1745 |
| 1720 LInstruction* LChunkBuilder::DoFunctionLiteral(HFunctionLiteral* instr) { | 1746 LInstruction* LChunkBuilder::DoFunctionLiteral(HFunctionLiteral* instr) { |
| 1721 return MarkAsCall(DefineFixed(new LFunctionLiteral, r0), instr); | 1747 return MarkAsCall(DefineFixed(new LFunctionLiteral, r0), instr); |
| 1722 } | 1748 } |
| 1723 | 1749 |
| 1724 | 1750 |
| 1725 LInstruction* LChunkBuilder::DoDeleteProperty(HDeleteProperty* instr) { | 1751 LInstruction* LChunkBuilder::DoDeleteProperty(HDeleteProperty* instr) { |
| 1726 LOperand* object = UseRegisterAtStart(instr->object()); | 1752 LOperand* object = UseRegisterAtStart(instr->object()); |
| 1727 LOperand* key = UseRegisterAtStart(instr->key()); | 1753 LOperand* key = UseRegisterAtStart(instr->key()); |
| 1728 LInstruction* result = new LDeleteProperty(object, key); | 1754 LDeleteProperty* result = new LDeleteProperty(object, key); |
| 1729 return MarkAsCall(DefineFixed(result, r0), instr); | 1755 return MarkAsCall(DefineFixed(result, r0), instr); |
| 1730 } | 1756 } |
| 1731 | 1757 |
| 1732 | 1758 |
| 1733 LInstruction* LChunkBuilder::DoOsrEntry(HOsrEntry* instr) { | 1759 LInstruction* LChunkBuilder::DoOsrEntry(HOsrEntry* instr) { |
| 1734 allocator_->MarkAsOsrEntry(); | 1760 allocator_->MarkAsOsrEntry(); |
| 1735 current_block_->last_environment()->set_ast_id(instr->ast_id()); | 1761 current_block_->last_environment()->set_ast_id(instr->ast_id()); |
| 1736 return AssignEnvironment(new LOsrEntry); | 1762 return AssignEnvironment(new LOsrEntry); |
| 1737 } | 1763 } |
| 1738 | 1764 |
| (...skipping 20 matching lines...) Expand all Loading... |
| 1759 // There are no real uses of the arguments object (we bail out in all other | 1785 // There are no real uses of the arguments object (we bail out in all other |
| 1760 // cases). | 1786 // cases). |
| 1761 return NULL; | 1787 return NULL; |
| 1762 } | 1788 } |
| 1763 | 1789 |
| 1764 | 1790 |
| 1765 LInstruction* LChunkBuilder::DoAccessArgumentsAt(HAccessArgumentsAt* instr) { | 1791 LInstruction* LChunkBuilder::DoAccessArgumentsAt(HAccessArgumentsAt* instr) { |
| 1766 LOperand* arguments = UseRegister(instr->arguments()); | 1792 LOperand* arguments = UseRegister(instr->arguments()); |
| 1767 LOperand* length = UseTempRegister(instr->length()); | 1793 LOperand* length = UseTempRegister(instr->length()); |
| 1768 LOperand* index = UseRegister(instr->index()); | 1794 LOperand* index = UseRegister(instr->index()); |
| 1769 LInstruction* result = new LAccessArgumentsAt(arguments, length, index); | 1795 LAccessArgumentsAt* result = new LAccessArgumentsAt(arguments, length, index); |
| 1770 return DefineAsRegister(AssignEnvironment(result)); | 1796 return AssignEnvironment(DefineAsRegister(result)); |
| 1771 } | 1797 } |
| 1772 | 1798 |
| 1773 | 1799 |
| 1774 LInstruction* LChunkBuilder::DoTypeof(HTypeof* instr) { | 1800 LInstruction* LChunkBuilder::DoTypeof(HTypeof* instr) { |
| 1775 LInstruction* result = new LTypeof(UseRegisterAtStart(instr->value())); | 1801 LTypeof* result = new LTypeof(UseRegisterAtStart(instr->value())); |
| 1776 return MarkAsCall(DefineFixed(result, r0), instr); | 1802 return MarkAsCall(DefineFixed(result, r0), instr); |
| 1777 } | 1803 } |
| 1778 | 1804 |
| 1779 | 1805 |
| 1780 LInstruction* LChunkBuilder::DoTypeofIs(HTypeofIs* instr) { | 1806 LInstruction* LChunkBuilder::DoTypeofIs(HTypeofIs* instr) { |
| 1781 return DefineSameAsFirst(new LTypeofIs(UseRegister(instr->value()))); | 1807 return DefineSameAsFirst(new LTypeofIs(UseRegister(instr->value()))); |
| 1782 } | 1808 } |
| 1783 | 1809 |
| 1784 LInstruction* LChunkBuilder::DoSimulate(HSimulate* instr) { | 1810 LInstruction* LChunkBuilder::DoSimulate(HSimulate* instr) { |
| 1785 HEnvironment* env = current_block_->last_environment(); | 1811 HEnvironment* env = current_block_->last_environment(); |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1833 | 1859 |
| 1834 | 1860 |
| 1835 LInstruction* LChunkBuilder::DoLeaveInlined(HLeaveInlined* instr) { | 1861 LInstruction* LChunkBuilder::DoLeaveInlined(HLeaveInlined* instr) { |
| 1836 HEnvironment* outer = current_block_->last_environment()->outer(); | 1862 HEnvironment* outer = current_block_->last_environment()->outer(); |
| 1837 current_block_->UpdateEnvironment(outer); | 1863 current_block_->UpdateEnvironment(outer); |
| 1838 return NULL; | 1864 return NULL; |
| 1839 } | 1865 } |
| 1840 | 1866 |
| 1841 | 1867 |
| 1842 } } // namespace v8::internal | 1868 } } // namespace v8::internal |
| OLD | NEW |