| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/v8.h" | 5 #include "src/v8.h" |
| 6 | 6 |
| 7 #if V8_TARGET_ARCH_X64 | 7 #if V8_TARGET_ARCH_X64 |
| 8 | 8 |
| 9 #include "src/hydrogen-osr.h" | 9 #include "src/hydrogen-osr.h" |
| 10 #include "src/lithium-inl.h" | 10 #include "src/lithium-inl.h" |
| 11 #include "src/x64/lithium-codegen-x64.h" | 11 #include "src/x64/lithium-codegen-x64.h" |
| 12 | 12 |
| 13 namespace v8 { | 13 namespace v8 { |
| 14 namespace internal { | 14 namespace internal { |
| 15 | 15 |
| 16 #define DEFINE_COMPILE(type) \ | 16 #define DEFINE_COMPILE(type) \ |
| 17 void L##type::CompileToNative(LCodeGen* generator) { \ | 17 void L##type::CompileToNative(LCodeGen* generator) { \ |
| 18 generator->Do##type(this); \ | 18 generator->Do##type(this); \ |
| 19 } | 19 } |
| 20 LITHIUM_CONCRETE_INSTRUCTION_LIST(DEFINE_COMPILE) | 20 LITHIUM_CONCRETE_INSTRUCTION_LIST(DEFINE_COMPILE) |
| 21 #undef DEFINE_COMPILE | 21 #undef DEFINE_COMPILE |
| 22 | 22 |
| 23 | 23 |
| 24 #ifdef DEBUG | 24 #ifdef DEBUG |
| 25 void LInstruction::VerifyCall() { | 25 void LInstruction::VerifyCall() { |
| 26 // Call instructions can use only fixed registers as temporaries and | 26 // Call instructions can use only fixed registers as temporaries and |
| 27 // outputs because all registers are blocked by the calling convention. | 27 // outputs because all registers are blocked by the calling convention. |
| 28 // Inputs operands must use a fixed register or use-at-start policy or | 28 // Inputs operands must use a fixed register or use-at-start policy or |
| 29 // a non-register policy. | 29 // a non-register policy. |
| 30 ASSERT(Output() == NULL || | 30 DCHECK(Output() == NULL || |
| 31 LUnallocated::cast(Output())->HasFixedPolicy() || | 31 LUnallocated::cast(Output())->HasFixedPolicy() || |
| 32 !LUnallocated::cast(Output())->HasRegisterPolicy()); | 32 !LUnallocated::cast(Output())->HasRegisterPolicy()); |
| 33 for (UseIterator it(this); !it.Done(); it.Advance()) { | 33 for (UseIterator it(this); !it.Done(); it.Advance()) { |
| 34 LUnallocated* operand = LUnallocated::cast(it.Current()); | 34 LUnallocated* operand = LUnallocated::cast(it.Current()); |
| 35 ASSERT(operand->HasFixedPolicy() || | 35 DCHECK(operand->HasFixedPolicy() || |
| 36 operand->IsUsedAtStart()); | 36 operand->IsUsedAtStart()); |
| 37 } | 37 } |
| 38 for (TempIterator it(this); !it.Done(); it.Advance()) { | 38 for (TempIterator it(this); !it.Done(); it.Advance()) { |
| 39 LUnallocated* operand = LUnallocated::cast(it.Current()); | 39 LUnallocated* operand = LUnallocated::cast(it.Current()); |
| 40 ASSERT(operand->HasFixedPolicy() ||!operand->HasRegisterPolicy()); | 40 DCHECK(operand->HasFixedPolicy() ||!operand->HasRegisterPolicy()); |
| 41 } | 41 } |
| 42 } | 42 } |
| 43 #endif | 43 #endif |
| 44 | 44 |
| 45 | 45 |
| 46 void LInstruction::PrintTo(StringStream* stream) { | 46 void LInstruction::PrintTo(StringStream* stream) { |
| 47 stream->Add("%s ", this->Mnemonic()); | 47 stream->Add("%s ", this->Mnemonic()); |
| 48 | 48 |
| 49 PrintOutputOperandTo(stream); | 49 PrintOutputOperandTo(stream); |
| 50 | 50 |
| (...skipping 294 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 345 | 345 |
| 346 | 346 |
| 347 LOperand* LPlatformChunk::GetNextSpillSlot(RegisterKind kind) { | 347 LOperand* LPlatformChunk::GetNextSpillSlot(RegisterKind kind) { |
| 348 // All stack slots are Double stack slots on x64. | 348 // All stack slots are Double stack slots on x64. |
| 349 // Alternatively, at some point, start using half-size | 349 // Alternatively, at some point, start using half-size |
| 350 // stack slots for int32 values. | 350 // stack slots for int32 values. |
| 351 int index = GetNextSpillIndex(kind); | 351 int index = GetNextSpillIndex(kind); |
| 352 if (kind == DOUBLE_REGISTERS) { | 352 if (kind == DOUBLE_REGISTERS) { |
| 353 return LDoubleStackSlot::Create(index, zone()); | 353 return LDoubleStackSlot::Create(index, zone()); |
| 354 } else { | 354 } else { |
| 355 ASSERT(kind == GENERAL_REGISTERS); | 355 DCHECK(kind == GENERAL_REGISTERS); |
| 356 return LStackSlot::Create(index, zone()); | 356 return LStackSlot::Create(index, zone()); |
| 357 } | 357 } |
| 358 } | 358 } |
| 359 | 359 |
| 360 | 360 |
| 361 void LStoreNamedField::PrintDataTo(StringStream* stream) { | 361 void LStoreNamedField::PrintDataTo(StringStream* stream) { |
| 362 object()->PrintTo(stream); | 362 object()->PrintTo(stream); |
| 363 OStringStream os; | 363 OStringStream os; |
| 364 os << hydrogen()->access() << " <- "; | 364 os << hydrogen()->access() << " <- "; |
| 365 stream->Add(os.c_str()); | 365 stream->Add(os.c_str()); |
| (...skipping 26 matching lines...) Expand all Loading... |
| 392 elements()->PrintTo(stream); | 392 elements()->PrintTo(stream); |
| 393 stream->Add("["); | 393 stream->Add("["); |
| 394 key()->PrintTo(stream); | 394 key()->PrintTo(stream); |
| 395 if (hydrogen()->IsDehoisted()) { | 395 if (hydrogen()->IsDehoisted()) { |
| 396 stream->Add(" + %d] <-", base_offset()); | 396 stream->Add(" + %d] <-", base_offset()); |
| 397 } else { | 397 } else { |
| 398 stream->Add("] <- "); | 398 stream->Add("] <- "); |
| 399 } | 399 } |
| 400 | 400 |
| 401 if (value() == NULL) { | 401 if (value() == NULL) { |
| 402 ASSERT(hydrogen()->IsConstantHoleStore() && | 402 DCHECK(hydrogen()->IsConstantHoleStore() && |
| 403 hydrogen()->value()->representation().IsDouble()); | 403 hydrogen()->value()->representation().IsDouble()); |
| 404 stream->Add("<the hole(nan)>"); | 404 stream->Add("<the hole(nan)>"); |
| 405 } else { | 405 } else { |
| 406 value()->PrintTo(stream); | 406 value()->PrintTo(stream); |
| 407 } | 407 } |
| 408 } | 408 } |
| 409 | 409 |
| 410 | 410 |
| 411 void LStoreKeyedGeneric::PrintDataTo(StringStream* stream) { | 411 void LStoreKeyedGeneric::PrintDataTo(StringStream* stream) { |
| 412 object()->PrintTo(stream); | 412 object()->PrintTo(stream); |
| 413 stream->Add("["); | 413 stream->Add("["); |
| 414 key()->PrintTo(stream); | 414 key()->PrintTo(stream); |
| 415 stream->Add("] <- "); | 415 stream->Add("] <- "); |
| 416 value()->PrintTo(stream); | 416 value()->PrintTo(stream); |
| 417 } | 417 } |
| 418 | 418 |
| 419 | 419 |
| 420 void LTransitionElementsKind::PrintDataTo(StringStream* stream) { | 420 void LTransitionElementsKind::PrintDataTo(StringStream* stream) { |
| 421 object()->PrintTo(stream); | 421 object()->PrintTo(stream); |
| 422 stream->Add(" %p -> %p", *original_map(), *transitioned_map()); | 422 stream->Add(" %p -> %p", *original_map(), *transitioned_map()); |
| 423 } | 423 } |
| 424 | 424 |
| 425 | 425 |
| 426 LPlatformChunk* LChunkBuilder::Build() { | 426 LPlatformChunk* LChunkBuilder::Build() { |
| 427 ASSERT(is_unused()); | 427 DCHECK(is_unused()); |
| 428 chunk_ = new(zone()) LPlatformChunk(info(), graph()); | 428 chunk_ = new(zone()) LPlatformChunk(info(), graph()); |
| 429 LPhase phase("L_Building chunk", chunk_); | 429 LPhase phase("L_Building chunk", chunk_); |
| 430 status_ = BUILDING; | 430 status_ = BUILDING; |
| 431 | 431 |
| 432 // If compiling for OSR, reserve space for the unoptimized frame, | 432 // If compiling for OSR, reserve space for the unoptimized frame, |
| 433 // which will be subsumed into this frame. | 433 // which will be subsumed into this frame. |
| 434 if (graph()->has_osr()) { | 434 if (graph()->has_osr()) { |
| 435 for (int i = graph()->osr()->UnoptimizedFrameSlots(); i > 0; i--) { | 435 for (int i = graph()->osr()->UnoptimizedFrameSlots(); i > 0; i--) { |
| 436 chunk_->GetNextSpillIndex(GENERAL_REGISTERS); | 436 chunk_->GetNextSpillIndex(GENERAL_REGISTERS); |
| 437 } | 437 } |
| (...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 638 instr = AssignEnvironment(instr); | 638 instr = AssignEnvironment(instr); |
| 639 // We can't really figure out if the environment is needed or not. | 639 // We can't really figure out if the environment is needed or not. |
| 640 instr->environment()->set_has_been_used(); | 640 instr->environment()->set_has_been_used(); |
| 641 } | 641 } |
| 642 | 642 |
| 643 return instr; | 643 return instr; |
| 644 } | 644 } |
| 645 | 645 |
| 646 | 646 |
| 647 LInstruction* LChunkBuilder::AssignPointerMap(LInstruction* instr) { | 647 LInstruction* LChunkBuilder::AssignPointerMap(LInstruction* instr) { |
| 648 ASSERT(!instr->HasPointerMap()); | 648 DCHECK(!instr->HasPointerMap()); |
| 649 instr->set_pointer_map(new(zone()) LPointerMap(zone())); | 649 instr->set_pointer_map(new(zone()) LPointerMap(zone())); |
| 650 return instr; | 650 return instr; |
| 651 } | 651 } |
| 652 | 652 |
| 653 | 653 |
| 654 LUnallocated* LChunkBuilder::TempRegister() { | 654 LUnallocated* LChunkBuilder::TempRegister() { |
| 655 LUnallocated* operand = | 655 LUnallocated* operand = |
| 656 new(zone()) LUnallocated(LUnallocated::MUST_HAVE_REGISTER); | 656 new(zone()) LUnallocated(LUnallocated::MUST_HAVE_REGISTER); |
| 657 int vreg = allocator_->GetVirtualRegister(); | 657 int vreg = allocator_->GetVirtualRegister(); |
| 658 if (!allocator_->AllocationOk()) { | 658 if (!allocator_->AllocationOk()) { |
| 659 Abort(kOutOfVirtualRegistersWhileTryingToAllocateTempRegister); | 659 Abort(kOutOfVirtualRegistersWhileTryingToAllocateTempRegister); |
| 660 vreg = 0; | 660 vreg = 0; |
| 661 } | 661 } |
| 662 operand->set_virtual_register(vreg); | 662 operand->set_virtual_register(vreg); |
| 663 return operand; | 663 return operand; |
| 664 } | 664 } |
| 665 | 665 |
| 666 | 666 |
| 667 LOperand* LChunkBuilder::FixedTemp(Register reg) { | 667 LOperand* LChunkBuilder::FixedTemp(Register reg) { |
| 668 LUnallocated* operand = ToUnallocated(reg); | 668 LUnallocated* operand = ToUnallocated(reg); |
| 669 ASSERT(operand->HasFixedPolicy()); | 669 DCHECK(operand->HasFixedPolicy()); |
| 670 return operand; | 670 return operand; |
| 671 } | 671 } |
| 672 | 672 |
| 673 | 673 |
| 674 LOperand* LChunkBuilder::FixedTemp(XMMRegister reg) { | 674 LOperand* LChunkBuilder::FixedTemp(XMMRegister reg) { |
| 675 LUnallocated* operand = ToUnallocated(reg); | 675 LUnallocated* operand = ToUnallocated(reg); |
| 676 ASSERT(operand->HasFixedPolicy()); | 676 DCHECK(operand->HasFixedPolicy()); |
| 677 return operand; | 677 return operand; |
| 678 } | 678 } |
| 679 | 679 |
| 680 | 680 |
| 681 LInstruction* LChunkBuilder::DoBlockEntry(HBlockEntry* instr) { | 681 LInstruction* LChunkBuilder::DoBlockEntry(HBlockEntry* instr) { |
| 682 return new(zone()) LLabel(instr->block()); | 682 return new(zone()) LLabel(instr->block()); |
| 683 } | 683 } |
| 684 | 684 |
| 685 | 685 |
| 686 LInstruction* LChunkBuilder::DoDummyUse(HDummyUse* instr) { | 686 LInstruction* LChunkBuilder::DoDummyUse(HDummyUse* instr) { |
| 687 return DefineAsRegister(new(zone()) LDummyUse(UseAny(instr->value()))); | 687 return DefineAsRegister(new(zone()) LDummyUse(UseAny(instr->value()))); |
| 688 } | 688 } |
| 689 | 689 |
| 690 | 690 |
| 691 LInstruction* LChunkBuilder::DoEnvironmentMarker(HEnvironmentMarker* instr) { | 691 LInstruction* LChunkBuilder::DoEnvironmentMarker(HEnvironmentMarker* instr) { |
| 692 UNREACHABLE(); | 692 UNREACHABLE(); |
| 693 return NULL; | 693 return NULL; |
| 694 } | 694 } |
| 695 | 695 |
| 696 | 696 |
| 697 LInstruction* LChunkBuilder::DoDeoptimize(HDeoptimize* instr) { | 697 LInstruction* LChunkBuilder::DoDeoptimize(HDeoptimize* instr) { |
| 698 return AssignEnvironment(new(zone()) LDeoptimize); | 698 return AssignEnvironment(new(zone()) LDeoptimize); |
| 699 } | 699 } |
| 700 | 700 |
| 701 | 701 |
| 702 LInstruction* LChunkBuilder::DoShift(Token::Value op, | 702 LInstruction* LChunkBuilder::DoShift(Token::Value op, |
| 703 HBitwiseBinaryOperation* instr) { | 703 HBitwiseBinaryOperation* instr) { |
| 704 if (instr->representation().IsSmiOrInteger32()) { | 704 if (instr->representation().IsSmiOrInteger32()) { |
| 705 ASSERT(instr->left()->representation().Equals(instr->representation())); | 705 DCHECK(instr->left()->representation().Equals(instr->representation())); |
| 706 ASSERT(instr->right()->representation().Equals(instr->representation())); | 706 DCHECK(instr->right()->representation().Equals(instr->representation())); |
| 707 LOperand* left = UseRegisterAtStart(instr->left()); | 707 LOperand* left = UseRegisterAtStart(instr->left()); |
| 708 | 708 |
| 709 HValue* right_value = instr->right(); | 709 HValue* right_value = instr->right(); |
| 710 LOperand* right = NULL; | 710 LOperand* right = NULL; |
| 711 int constant_value = 0; | 711 int constant_value = 0; |
| 712 bool does_deopt = false; | 712 bool does_deopt = false; |
| 713 if (right_value->IsConstant()) { | 713 if (right_value->IsConstant()) { |
| 714 HConstant* constant = HConstant::cast(right_value); | 714 HConstant* constant = HConstant::cast(right_value); |
| 715 right = chunk_->DefineConstantOperand(constant); | 715 right = chunk_->DefineConstantOperand(constant); |
| 716 constant_value = constant->Integer32Value() & 0x1f; | 716 constant_value = constant->Integer32Value() & 0x1f; |
| (...skipping 21 matching lines...) Expand all Loading... |
| 738 DefineSameAsFirst(new(zone()) LShiftI(op, left, right, does_deopt)); | 738 DefineSameAsFirst(new(zone()) LShiftI(op, left, right, does_deopt)); |
| 739 return does_deopt ? AssignEnvironment(result) : result; | 739 return does_deopt ? AssignEnvironment(result) : result; |
| 740 } else { | 740 } else { |
| 741 return DoArithmeticT(op, instr); | 741 return DoArithmeticT(op, instr); |
| 742 } | 742 } |
| 743 } | 743 } |
| 744 | 744 |
| 745 | 745 |
| 746 LInstruction* LChunkBuilder::DoArithmeticD(Token::Value op, | 746 LInstruction* LChunkBuilder::DoArithmeticD(Token::Value op, |
| 747 HArithmeticBinaryOperation* instr) { | 747 HArithmeticBinaryOperation* instr) { |
| 748 ASSERT(instr->representation().IsDouble()); | 748 DCHECK(instr->representation().IsDouble()); |
| 749 ASSERT(instr->left()->representation().IsDouble()); | 749 DCHECK(instr->left()->representation().IsDouble()); |
| 750 ASSERT(instr->right()->representation().IsDouble()); | 750 DCHECK(instr->right()->representation().IsDouble()); |
| 751 if (op == Token::MOD) { | 751 if (op == Token::MOD) { |
| 752 LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand()); | 752 LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand()); |
| 753 LOperand* right = UseFixedDouble(instr->BetterRightOperand(), xmm1); | 753 LOperand* right = UseFixedDouble(instr->BetterRightOperand(), xmm1); |
| 754 LArithmeticD* result = new(zone()) LArithmeticD(op, left, right); | 754 LArithmeticD* result = new(zone()) LArithmeticD(op, left, right); |
| 755 return MarkAsCall(DefineSameAsFirst(result), instr); | 755 return MarkAsCall(DefineSameAsFirst(result), instr); |
| 756 } else { | 756 } else { |
| 757 LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand()); | 757 LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand()); |
| 758 LOperand* right = UseRegisterAtStart(instr->BetterRightOperand()); | 758 LOperand* right = UseRegisterAtStart(instr->BetterRightOperand()); |
| 759 LArithmeticD* result = new(zone()) LArithmeticD(op, left, right); | 759 LArithmeticD* result = new(zone()) LArithmeticD(op, left, right); |
| 760 return DefineSameAsFirst(result); | 760 return DefineSameAsFirst(result); |
| 761 } | 761 } |
| 762 } | 762 } |
| 763 | 763 |
| 764 | 764 |
| 765 LInstruction* LChunkBuilder::DoArithmeticT(Token::Value op, | 765 LInstruction* LChunkBuilder::DoArithmeticT(Token::Value op, |
| 766 HBinaryOperation* instr) { | 766 HBinaryOperation* instr) { |
| 767 HValue* left = instr->left(); | 767 HValue* left = instr->left(); |
| 768 HValue* right = instr->right(); | 768 HValue* right = instr->right(); |
| 769 ASSERT(left->representation().IsTagged()); | 769 DCHECK(left->representation().IsTagged()); |
| 770 ASSERT(right->representation().IsTagged()); | 770 DCHECK(right->representation().IsTagged()); |
| 771 LOperand* context = UseFixed(instr->context(), rsi); | 771 LOperand* context = UseFixed(instr->context(), rsi); |
| 772 LOperand* left_operand = UseFixed(left, rdx); | 772 LOperand* left_operand = UseFixed(left, rdx); |
| 773 LOperand* right_operand = UseFixed(right, rax); | 773 LOperand* right_operand = UseFixed(right, rax); |
| 774 LArithmeticT* result = | 774 LArithmeticT* result = |
| 775 new(zone()) LArithmeticT(op, context, left_operand, right_operand); | 775 new(zone()) LArithmeticT(op, context, left_operand, right_operand); |
| 776 return MarkAsCall(DefineFixed(result, rax), instr); | 776 return MarkAsCall(DefineFixed(result, rax), instr); |
| 777 } | 777 } |
| 778 | 778 |
| 779 | 779 |
| 780 void LChunkBuilder::DoBasicBlock(HBasicBlock* block, HBasicBlock* next_block) { | 780 void LChunkBuilder::DoBasicBlock(HBasicBlock* block, HBasicBlock* next_block) { |
| 781 ASSERT(is_building()); | 781 DCHECK(is_building()); |
| 782 current_block_ = block; | 782 current_block_ = block; |
| 783 next_block_ = next_block; | 783 next_block_ = next_block; |
| 784 if (block->IsStartBlock()) { | 784 if (block->IsStartBlock()) { |
| 785 block->UpdateEnvironment(graph_->start_environment()); | 785 block->UpdateEnvironment(graph_->start_environment()); |
| 786 argument_count_ = 0; | 786 argument_count_ = 0; |
| 787 } else if (block->predecessors()->length() == 1) { | 787 } else if (block->predecessors()->length() == 1) { |
| 788 // We have a single predecessor => copy environment and outgoing | 788 // We have a single predecessor => copy environment and outgoing |
| 789 // argument count from the predecessor. | 789 // argument count from the predecessor. |
| 790 ASSERT(block->phis()->length() == 0); | 790 DCHECK(block->phis()->length() == 0); |
| 791 HBasicBlock* pred = block->predecessors()->at(0); | 791 HBasicBlock* pred = block->predecessors()->at(0); |
| 792 HEnvironment* last_environment = pred->last_environment(); | 792 HEnvironment* last_environment = pred->last_environment(); |
| 793 ASSERT(last_environment != NULL); | 793 DCHECK(last_environment != NULL); |
| 794 // Only copy the environment, if it is later used again. | 794 // Only copy the environment, if it is later used again. |
| 795 if (pred->end()->SecondSuccessor() == NULL) { | 795 if (pred->end()->SecondSuccessor() == NULL) { |
| 796 ASSERT(pred->end()->FirstSuccessor() == block); | 796 DCHECK(pred->end()->FirstSuccessor() == block); |
| 797 } else { | 797 } else { |
| 798 if (pred->end()->FirstSuccessor()->block_id() > block->block_id() || | 798 if (pred->end()->FirstSuccessor()->block_id() > block->block_id() || |
| 799 pred->end()->SecondSuccessor()->block_id() > block->block_id()) { | 799 pred->end()->SecondSuccessor()->block_id() > block->block_id()) { |
| 800 last_environment = last_environment->Copy(); | 800 last_environment = last_environment->Copy(); |
| 801 } | 801 } |
| 802 } | 802 } |
| 803 block->UpdateEnvironment(last_environment); | 803 block->UpdateEnvironment(last_environment); |
| 804 ASSERT(pred->argument_count() >= 0); | 804 DCHECK(pred->argument_count() >= 0); |
| 805 argument_count_ = pred->argument_count(); | 805 argument_count_ = pred->argument_count(); |
| 806 } else { | 806 } else { |
| 807 // We are at a state join => process phis. | 807 // We are at a state join => process phis. |
| 808 HBasicBlock* pred = block->predecessors()->at(0); | 808 HBasicBlock* pred = block->predecessors()->at(0); |
| 809 // No need to copy the environment, it cannot be used later. | 809 // No need to copy the environment, it cannot be used later. |
| 810 HEnvironment* last_environment = pred->last_environment(); | 810 HEnvironment* last_environment = pred->last_environment(); |
| 811 for (int i = 0; i < block->phis()->length(); ++i) { | 811 for (int i = 0; i < block->phis()->length(); ++i) { |
| 812 HPhi* phi = block->phis()->at(i); | 812 HPhi* phi = block->phis()->at(i); |
| 813 if (phi->HasMergedIndex()) { | 813 if (phi->HasMergedIndex()) { |
| 814 last_environment->SetValueAt(phi->merged_index(), phi); | 814 last_environment->SetValueAt(phi->merged_index(), phi); |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 846 | 846 |
| 847 void LChunkBuilder::VisitInstruction(HInstruction* current) { | 847 void LChunkBuilder::VisitInstruction(HInstruction* current) { |
| 848 HInstruction* old_current = current_instruction_; | 848 HInstruction* old_current = current_instruction_; |
| 849 current_instruction_ = current; | 849 current_instruction_ = current; |
| 850 | 850 |
| 851 LInstruction* instr = NULL; | 851 LInstruction* instr = NULL; |
| 852 if (current->CanReplaceWithDummyUses()) { | 852 if (current->CanReplaceWithDummyUses()) { |
| 853 if (current->OperandCount() == 0) { | 853 if (current->OperandCount() == 0) { |
| 854 instr = DefineAsRegister(new(zone()) LDummy()); | 854 instr = DefineAsRegister(new(zone()) LDummy()); |
| 855 } else { | 855 } else { |
| 856 ASSERT(!current->OperandAt(0)->IsControlInstruction()); | 856 DCHECK(!current->OperandAt(0)->IsControlInstruction()); |
| 857 instr = DefineAsRegister(new(zone()) | 857 instr = DefineAsRegister(new(zone()) |
| 858 LDummyUse(UseAny(current->OperandAt(0)))); | 858 LDummyUse(UseAny(current->OperandAt(0)))); |
| 859 } | 859 } |
| 860 for (int i = 1; i < current->OperandCount(); ++i) { | 860 for (int i = 1; i < current->OperandCount(); ++i) { |
| 861 if (current->OperandAt(i)->IsControlInstruction()) continue; | 861 if (current->OperandAt(i)->IsControlInstruction()) continue; |
| 862 LInstruction* dummy = | 862 LInstruction* dummy = |
| 863 new(zone()) LDummyUse(UseAny(current->OperandAt(i))); | 863 new(zone()) LDummyUse(UseAny(current->OperandAt(i))); |
| 864 dummy->set_hydrogen_value(current); | 864 dummy->set_hydrogen_value(current); |
| 865 chunk_->AddInstruction(dummy, current_block_); | 865 chunk_->AddInstruction(dummy, current_block_); |
| 866 } | 866 } |
| 867 } else { | 867 } else { |
| 868 HBasicBlock* successor; | 868 HBasicBlock* successor; |
| 869 if (current->IsControlInstruction() && | 869 if (current->IsControlInstruction() && |
| 870 HControlInstruction::cast(current)->KnownSuccessorBlock(&successor) && | 870 HControlInstruction::cast(current)->KnownSuccessorBlock(&successor) && |
| 871 successor != NULL) { | 871 successor != NULL) { |
| 872 instr = new(zone()) LGoto(successor); | 872 instr = new(zone()) LGoto(successor); |
| 873 } else { | 873 } else { |
| 874 instr = current->CompileToLithium(this); | 874 instr = current->CompileToLithium(this); |
| 875 } | 875 } |
| 876 } | 876 } |
| 877 | 877 |
| 878 argument_count_ += current->argument_delta(); | 878 argument_count_ += current->argument_delta(); |
| 879 ASSERT(argument_count_ >= 0); | 879 DCHECK(argument_count_ >= 0); |
| 880 | 880 |
| 881 if (instr != NULL) { | 881 if (instr != NULL) { |
| 882 AddInstruction(instr, current); | 882 AddInstruction(instr, current); |
| 883 } | 883 } |
| 884 | 884 |
| 885 current_instruction_ = old_current; | 885 current_instruction_ = old_current; |
| 886 } | 886 } |
| 887 | 887 |
| 888 | 888 |
| 889 void LChunkBuilder::AddInstruction(LInstruction* instr, | 889 void LChunkBuilder::AddInstruction(LInstruction* instr, |
| (...skipping 21 matching lines...) Expand all Loading... |
| 911 LUnallocated* operand = LUnallocated::cast(it.Current()); | 911 LUnallocated* operand = LUnallocated::cast(it.Current()); |
| 912 if (operand->IsUsedAtStart()) ++used_at_start; | 912 if (operand->IsUsedAtStart()) ++used_at_start; |
| 913 } | 913 } |
| 914 if (instr->Output() != NULL) { | 914 if (instr->Output() != NULL) { |
| 915 if (LUnallocated::cast(instr->Output())->HasFixedPolicy()) ++fixed; | 915 if (LUnallocated::cast(instr->Output())->HasFixedPolicy()) ++fixed; |
| 916 } | 916 } |
| 917 for (TempIterator it(instr); !it.Done(); it.Advance()) { | 917 for (TempIterator it(instr); !it.Done(); it.Advance()) { |
| 918 LUnallocated* operand = LUnallocated::cast(it.Current()); | 918 LUnallocated* operand = LUnallocated::cast(it.Current()); |
| 919 if (operand->HasFixedPolicy()) ++fixed; | 919 if (operand->HasFixedPolicy()) ++fixed; |
| 920 } | 920 } |
| 921 ASSERT(fixed == 0 || used_at_start == 0); | 921 DCHECK(fixed == 0 || used_at_start == 0); |
| 922 } | 922 } |
| 923 #endif | 923 #endif |
| 924 | 924 |
| 925 if (FLAG_stress_pointer_maps && !instr->HasPointerMap()) { | 925 if (FLAG_stress_pointer_maps && !instr->HasPointerMap()) { |
| 926 instr = AssignPointerMap(instr); | 926 instr = AssignPointerMap(instr); |
| 927 } | 927 } |
| 928 if (FLAG_stress_environments && !instr->HasEnvironment()) { | 928 if (FLAG_stress_environments && !instr->HasEnvironment()) { |
| 929 instr = AssignEnvironment(instr); | 929 instr = AssignEnvironment(instr); |
| 930 } | 930 } |
| 931 chunk_->AddInstruction(instr, current_block_); | 931 chunk_->AddInstruction(instr, current_block_); |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 975 if (!easy_case && | 975 if (!easy_case && |
| 976 ((!expected.Contains(ToBooleanStub::SMI) && expected.NeedsMap()) || | 976 ((!expected.Contains(ToBooleanStub::SMI) && expected.NeedsMap()) || |
| 977 !expected.IsGeneric())) { | 977 !expected.IsGeneric())) { |
| 978 branch = AssignEnvironment(branch); | 978 branch = AssignEnvironment(branch); |
| 979 } | 979 } |
| 980 return branch; | 980 return branch; |
| 981 } | 981 } |
| 982 | 982 |
| 983 | 983 |
| 984 LInstruction* LChunkBuilder::DoCompareMap(HCompareMap* instr) { | 984 LInstruction* LChunkBuilder::DoCompareMap(HCompareMap* instr) { |
| 985 ASSERT(instr->value()->representation().IsTagged()); | 985 DCHECK(instr->value()->representation().IsTagged()); |
| 986 LOperand* value = UseRegisterAtStart(instr->value()); | 986 LOperand* value = UseRegisterAtStart(instr->value()); |
| 987 return new(zone()) LCmpMapAndBranch(value); | 987 return new(zone()) LCmpMapAndBranch(value); |
| 988 } | 988 } |
| 989 | 989 |
| 990 | 990 |
| 991 LInstruction* LChunkBuilder::DoArgumentsLength(HArgumentsLength* length) { | 991 LInstruction* LChunkBuilder::DoArgumentsLength(HArgumentsLength* length) { |
| 992 info()->MarkAsRequiresFrame(); | 992 info()->MarkAsRequiresFrame(); |
| 993 return DefineAsRegister(new(zone()) LArgumentsLength(Use(length->value()))); | 993 return DefineAsRegister(new(zone()) LArgumentsLength(Use(length->value()))); |
| 994 } | 994 } |
| 995 | 995 |
| (...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1183 LInstruction* result = | 1183 LInstruction* result = |
| 1184 DefineSameAsFirst(new(zone()) LMathAbs(context, input)); | 1184 DefineSameAsFirst(new(zone()) LMathAbs(context, input)); |
| 1185 Representation r = instr->value()->representation(); | 1185 Representation r = instr->value()->representation(); |
| 1186 if (!r.IsDouble() && !r.IsSmiOrInteger32()) result = AssignPointerMap(result); | 1186 if (!r.IsDouble() && !r.IsSmiOrInteger32()) result = AssignPointerMap(result); |
| 1187 if (!r.IsDouble()) result = AssignEnvironment(result); | 1187 if (!r.IsDouble()) result = AssignEnvironment(result); |
| 1188 return result; | 1188 return result; |
| 1189 } | 1189 } |
| 1190 | 1190 |
| 1191 | 1191 |
| 1192 LInstruction* LChunkBuilder::DoMathLog(HUnaryMathOperation* instr) { | 1192 LInstruction* LChunkBuilder::DoMathLog(HUnaryMathOperation* instr) { |
| 1193 ASSERT(instr->representation().IsDouble()); | 1193 DCHECK(instr->representation().IsDouble()); |
| 1194 ASSERT(instr->value()->representation().IsDouble()); | 1194 DCHECK(instr->value()->representation().IsDouble()); |
| 1195 LOperand* input = UseRegisterAtStart(instr->value()); | 1195 LOperand* input = UseRegisterAtStart(instr->value()); |
| 1196 return MarkAsCall(DefineSameAsFirst(new(zone()) LMathLog(input)), instr); | 1196 return MarkAsCall(DefineSameAsFirst(new(zone()) LMathLog(input)), instr); |
| 1197 } | 1197 } |
| 1198 | 1198 |
| 1199 | 1199 |
| 1200 LInstruction* LChunkBuilder::DoMathClz32(HUnaryMathOperation* instr) { | 1200 LInstruction* LChunkBuilder::DoMathClz32(HUnaryMathOperation* instr) { |
| 1201 LOperand* input = UseRegisterAtStart(instr->value()); | 1201 LOperand* input = UseRegisterAtStart(instr->value()); |
| 1202 LMathClz32* result = new(zone()) LMathClz32(input); | 1202 LMathClz32* result = new(zone()) LMathClz32(input); |
| 1203 return DefineAsRegister(result); | 1203 return DefineAsRegister(result); |
| 1204 } | 1204 } |
| 1205 | 1205 |
| 1206 | 1206 |
| 1207 LInstruction* LChunkBuilder::DoMathExp(HUnaryMathOperation* instr) { | 1207 LInstruction* LChunkBuilder::DoMathExp(HUnaryMathOperation* instr) { |
| 1208 ASSERT(instr->representation().IsDouble()); | 1208 DCHECK(instr->representation().IsDouble()); |
| 1209 ASSERT(instr->value()->representation().IsDouble()); | 1209 DCHECK(instr->value()->representation().IsDouble()); |
| 1210 LOperand* value = UseTempRegister(instr->value()); | 1210 LOperand* value = UseTempRegister(instr->value()); |
| 1211 LOperand* temp1 = TempRegister(); | 1211 LOperand* temp1 = TempRegister(); |
| 1212 LOperand* temp2 = TempRegister(); | 1212 LOperand* temp2 = TempRegister(); |
| 1213 LMathExp* result = new(zone()) LMathExp(value, temp1, temp2); | 1213 LMathExp* result = new(zone()) LMathExp(value, temp1, temp2); |
| 1214 return DefineAsRegister(result); | 1214 return DefineAsRegister(result); |
| 1215 } | 1215 } |
| 1216 | 1216 |
| 1217 | 1217 |
| 1218 LInstruction* LChunkBuilder::DoMathSqrt(HUnaryMathOperation* instr) { | 1218 LInstruction* LChunkBuilder::DoMathSqrt(HUnaryMathOperation* instr) { |
| 1219 LOperand* input = UseAtStart(instr->value()); | 1219 LOperand* input = UseAtStart(instr->value()); |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1274 } | 1274 } |
| 1275 | 1275 |
| 1276 | 1276 |
| 1277 LInstruction* LChunkBuilder::DoShl(HShl* instr) { | 1277 LInstruction* LChunkBuilder::DoShl(HShl* instr) { |
| 1278 return DoShift(Token::SHL, instr); | 1278 return DoShift(Token::SHL, instr); |
| 1279 } | 1279 } |
| 1280 | 1280 |
| 1281 | 1281 |
| 1282 LInstruction* LChunkBuilder::DoBitwise(HBitwise* instr) { | 1282 LInstruction* LChunkBuilder::DoBitwise(HBitwise* instr) { |
| 1283 if (instr->representation().IsSmiOrInteger32()) { | 1283 if (instr->representation().IsSmiOrInteger32()) { |
| 1284 ASSERT(instr->left()->representation().Equals(instr->representation())); | 1284 DCHECK(instr->left()->representation().Equals(instr->representation())); |
| 1285 ASSERT(instr->right()->representation().Equals(instr->representation())); | 1285 DCHECK(instr->right()->representation().Equals(instr->representation())); |
| 1286 ASSERT(instr->CheckFlag(HValue::kTruncatingToInt32)); | 1286 DCHECK(instr->CheckFlag(HValue::kTruncatingToInt32)); |
| 1287 | 1287 |
| 1288 LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand()); | 1288 LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand()); |
| 1289 LOperand* right = UseOrConstantAtStart(instr->BetterRightOperand()); | 1289 LOperand* right = UseOrConstantAtStart(instr->BetterRightOperand()); |
| 1290 return DefineSameAsFirst(new(zone()) LBitI(left, right)); | 1290 return DefineSameAsFirst(new(zone()) LBitI(left, right)); |
| 1291 } else { | 1291 } else { |
| 1292 return DoArithmeticT(instr->op(), instr); | 1292 return DoArithmeticT(instr->op(), instr); |
| 1293 } | 1293 } |
| 1294 } | 1294 } |
| 1295 | 1295 |
| 1296 | 1296 |
| 1297 LInstruction* LChunkBuilder::DoDivByPowerOf2I(HDiv* instr) { | 1297 LInstruction* LChunkBuilder::DoDivByPowerOf2I(HDiv* instr) { |
| 1298 ASSERT(instr->representation().IsSmiOrInteger32()); | 1298 DCHECK(instr->representation().IsSmiOrInteger32()); |
| 1299 ASSERT(instr->left()->representation().Equals(instr->representation())); | 1299 DCHECK(instr->left()->representation().Equals(instr->representation())); |
| 1300 ASSERT(instr->right()->representation().Equals(instr->representation())); | 1300 DCHECK(instr->right()->representation().Equals(instr->representation())); |
| 1301 LOperand* dividend = UseRegister(instr->left()); | 1301 LOperand* dividend = UseRegister(instr->left()); |
| 1302 int32_t divisor = instr->right()->GetInteger32Constant(); | 1302 int32_t divisor = instr->right()->GetInteger32Constant(); |
| 1303 LInstruction* result = DefineAsRegister(new(zone()) LDivByPowerOf2I( | 1303 LInstruction* result = DefineAsRegister(new(zone()) LDivByPowerOf2I( |
| 1304 dividend, divisor)); | 1304 dividend, divisor)); |
| 1305 if ((instr->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) || | 1305 if ((instr->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) || |
| 1306 (instr->CheckFlag(HValue::kCanOverflow) && divisor == -1) || | 1306 (instr->CheckFlag(HValue::kCanOverflow) && divisor == -1) || |
| 1307 (!instr->CheckFlag(HInstruction::kAllUsesTruncatingToInt32) && | 1307 (!instr->CheckFlag(HInstruction::kAllUsesTruncatingToInt32) && |
| 1308 divisor != 1 && divisor != -1)) { | 1308 divisor != 1 && divisor != -1)) { |
| 1309 result = AssignEnvironment(result); | 1309 result = AssignEnvironment(result); |
| 1310 } | 1310 } |
| 1311 return result; | 1311 return result; |
| 1312 } | 1312 } |
| 1313 | 1313 |
| 1314 | 1314 |
| 1315 LInstruction* LChunkBuilder::DoDivByConstI(HDiv* instr) { | 1315 LInstruction* LChunkBuilder::DoDivByConstI(HDiv* instr) { |
| 1316 ASSERT(instr->representation().IsInteger32()); | 1316 DCHECK(instr->representation().IsInteger32()); |
| 1317 ASSERT(instr->left()->representation().Equals(instr->representation())); | 1317 DCHECK(instr->left()->representation().Equals(instr->representation())); |
| 1318 ASSERT(instr->right()->representation().Equals(instr->representation())); | 1318 DCHECK(instr->right()->representation().Equals(instr->representation())); |
| 1319 LOperand* dividend = UseRegister(instr->left()); | 1319 LOperand* dividend = UseRegister(instr->left()); |
| 1320 int32_t divisor = instr->right()->GetInteger32Constant(); | 1320 int32_t divisor = instr->right()->GetInteger32Constant(); |
| 1321 LOperand* temp1 = FixedTemp(rax); | 1321 LOperand* temp1 = FixedTemp(rax); |
| 1322 LOperand* temp2 = FixedTemp(rdx); | 1322 LOperand* temp2 = FixedTemp(rdx); |
| 1323 LInstruction* result = DefineFixed(new(zone()) LDivByConstI( | 1323 LInstruction* result = DefineFixed(new(zone()) LDivByConstI( |
| 1324 dividend, divisor, temp1, temp2), rdx); | 1324 dividend, divisor, temp1, temp2), rdx); |
| 1325 if (divisor == 0 || | 1325 if (divisor == 0 || |
| 1326 (instr->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) || | 1326 (instr->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) || |
| 1327 !instr->CheckFlag(HInstruction::kAllUsesTruncatingToInt32)) { | 1327 !instr->CheckFlag(HInstruction::kAllUsesTruncatingToInt32)) { |
| 1328 result = AssignEnvironment(result); | 1328 result = AssignEnvironment(result); |
| 1329 } | 1329 } |
| 1330 return result; | 1330 return result; |
| 1331 } | 1331 } |
| 1332 | 1332 |
| 1333 | 1333 |
| 1334 LInstruction* LChunkBuilder::DoDivI(HDiv* instr) { | 1334 LInstruction* LChunkBuilder::DoDivI(HDiv* instr) { |
| 1335 ASSERT(instr->representation().IsSmiOrInteger32()); | 1335 DCHECK(instr->representation().IsSmiOrInteger32()); |
| 1336 ASSERT(instr->left()->representation().Equals(instr->representation())); | 1336 DCHECK(instr->left()->representation().Equals(instr->representation())); |
| 1337 ASSERT(instr->right()->representation().Equals(instr->representation())); | 1337 DCHECK(instr->right()->representation().Equals(instr->representation())); |
| 1338 LOperand* dividend = UseFixed(instr->left(), rax); | 1338 LOperand* dividend = UseFixed(instr->left(), rax); |
| 1339 LOperand* divisor = UseRegister(instr->right()); | 1339 LOperand* divisor = UseRegister(instr->right()); |
| 1340 LOperand* temp = FixedTemp(rdx); | 1340 LOperand* temp = FixedTemp(rdx); |
| 1341 LInstruction* result = DefineFixed(new(zone()) LDivI( | 1341 LInstruction* result = DefineFixed(new(zone()) LDivI( |
| 1342 dividend, divisor, temp), rax); | 1342 dividend, divisor, temp), rax); |
| 1343 if (instr->CheckFlag(HValue::kCanBeDivByZero) || | 1343 if (instr->CheckFlag(HValue::kCanBeDivByZero) || |
| 1344 instr->CheckFlag(HValue::kBailoutOnMinusZero) || | 1344 instr->CheckFlag(HValue::kBailoutOnMinusZero) || |
| 1345 instr->CheckFlag(HValue::kCanOverflow) || | 1345 instr->CheckFlag(HValue::kCanOverflow) || |
| 1346 !instr->CheckFlag(HValue::kAllUsesTruncatingToInt32)) { | 1346 !instr->CheckFlag(HValue::kAllUsesTruncatingToInt32)) { |
| 1347 result = AssignEnvironment(result); | 1347 result = AssignEnvironment(result); |
| (...skipping 26 matching lines...) Expand all Loading... |
| 1374 dividend, divisor)); | 1374 dividend, divisor)); |
| 1375 if ((instr->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) || | 1375 if ((instr->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) || |
| 1376 (instr->CheckFlag(HValue::kLeftCanBeMinInt) && divisor == -1)) { | 1376 (instr->CheckFlag(HValue::kLeftCanBeMinInt) && divisor == -1)) { |
| 1377 result = AssignEnvironment(result); | 1377 result = AssignEnvironment(result); |
| 1378 } | 1378 } |
| 1379 return result; | 1379 return result; |
| 1380 } | 1380 } |
| 1381 | 1381 |
| 1382 | 1382 |
| 1383 LInstruction* LChunkBuilder::DoFlooringDivByConstI(HMathFloorOfDiv* instr) { | 1383 LInstruction* LChunkBuilder::DoFlooringDivByConstI(HMathFloorOfDiv* instr) { |
| 1384 ASSERT(instr->representation().IsInteger32()); | 1384 DCHECK(instr->representation().IsInteger32()); |
| 1385 ASSERT(instr->left()->representation().Equals(instr->representation())); | 1385 DCHECK(instr->left()->representation().Equals(instr->representation())); |
| 1386 ASSERT(instr->right()->representation().Equals(instr->representation())); | 1386 DCHECK(instr->right()->representation().Equals(instr->representation())); |
| 1387 LOperand* dividend = UseRegister(instr->left()); | 1387 LOperand* dividend = UseRegister(instr->left()); |
| 1388 int32_t divisor = instr->right()->GetInteger32Constant(); | 1388 int32_t divisor = instr->right()->GetInteger32Constant(); |
| 1389 LOperand* temp1 = FixedTemp(rax); | 1389 LOperand* temp1 = FixedTemp(rax); |
| 1390 LOperand* temp2 = FixedTemp(rdx); | 1390 LOperand* temp2 = FixedTemp(rdx); |
| 1391 LOperand* temp3 = | 1391 LOperand* temp3 = |
| 1392 ((divisor > 0 && !instr->CheckFlag(HValue::kLeftCanBeNegative)) || | 1392 ((divisor > 0 && !instr->CheckFlag(HValue::kLeftCanBeNegative)) || |
| 1393 (divisor < 0 && !instr->CheckFlag(HValue::kLeftCanBePositive))) ? | 1393 (divisor < 0 && !instr->CheckFlag(HValue::kLeftCanBePositive))) ? |
| 1394 NULL : TempRegister(); | 1394 NULL : TempRegister(); |
| 1395 LInstruction* result = | 1395 LInstruction* result = |
| 1396 DefineFixed(new(zone()) LFlooringDivByConstI(dividend, | 1396 DefineFixed(new(zone()) LFlooringDivByConstI(dividend, |
| 1397 divisor, | 1397 divisor, |
| 1398 temp1, | 1398 temp1, |
| 1399 temp2, | 1399 temp2, |
| 1400 temp3), | 1400 temp3), |
| 1401 rdx); | 1401 rdx); |
| 1402 if (divisor == 0 || | 1402 if (divisor == 0 || |
| 1403 (instr->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0)) { | 1403 (instr->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0)) { |
| 1404 result = AssignEnvironment(result); | 1404 result = AssignEnvironment(result); |
| 1405 } | 1405 } |
| 1406 return result; | 1406 return result; |
| 1407 } | 1407 } |
| 1408 | 1408 |
| 1409 | 1409 |
| 1410 LInstruction* LChunkBuilder::DoFlooringDivI(HMathFloorOfDiv* instr) { | 1410 LInstruction* LChunkBuilder::DoFlooringDivI(HMathFloorOfDiv* instr) { |
| 1411 ASSERT(instr->representation().IsSmiOrInteger32()); | 1411 DCHECK(instr->representation().IsSmiOrInteger32()); |
| 1412 ASSERT(instr->left()->representation().Equals(instr->representation())); | 1412 DCHECK(instr->left()->representation().Equals(instr->representation())); |
| 1413 ASSERT(instr->right()->representation().Equals(instr->representation())); | 1413 DCHECK(instr->right()->representation().Equals(instr->representation())); |
| 1414 LOperand* dividend = UseFixed(instr->left(), rax); | 1414 LOperand* dividend = UseFixed(instr->left(), rax); |
| 1415 LOperand* divisor = UseRegister(instr->right()); | 1415 LOperand* divisor = UseRegister(instr->right()); |
| 1416 LOperand* temp = FixedTemp(rdx); | 1416 LOperand* temp = FixedTemp(rdx); |
| 1417 LInstruction* result = DefineFixed(new(zone()) LFlooringDivI( | 1417 LInstruction* result = DefineFixed(new(zone()) LFlooringDivI( |
| 1418 dividend, divisor, temp), rax); | 1418 dividend, divisor, temp), rax); |
| 1419 if (instr->CheckFlag(HValue::kCanBeDivByZero) || | 1419 if (instr->CheckFlag(HValue::kCanBeDivByZero) || |
| 1420 instr->CheckFlag(HValue::kBailoutOnMinusZero) || | 1420 instr->CheckFlag(HValue::kBailoutOnMinusZero) || |
| 1421 instr->CheckFlag(HValue::kCanOverflow)) { | 1421 instr->CheckFlag(HValue::kCanOverflow)) { |
| 1422 result = AssignEnvironment(result); | 1422 result = AssignEnvironment(result); |
| 1423 } | 1423 } |
| 1424 return result; | 1424 return result; |
| 1425 } | 1425 } |
| 1426 | 1426 |
| 1427 | 1427 |
| 1428 LInstruction* LChunkBuilder::DoMathFloorOfDiv(HMathFloorOfDiv* instr) { | 1428 LInstruction* LChunkBuilder::DoMathFloorOfDiv(HMathFloorOfDiv* instr) { |
| 1429 if (instr->RightIsPowerOf2()) { | 1429 if (instr->RightIsPowerOf2()) { |
| 1430 return DoFlooringDivByPowerOf2I(instr); | 1430 return DoFlooringDivByPowerOf2I(instr); |
| 1431 } else if (instr->right()->IsConstant()) { | 1431 } else if (instr->right()->IsConstant()) { |
| 1432 return DoFlooringDivByConstI(instr); | 1432 return DoFlooringDivByConstI(instr); |
| 1433 } else { | 1433 } else { |
| 1434 return DoFlooringDivI(instr); | 1434 return DoFlooringDivI(instr); |
| 1435 } | 1435 } |
| 1436 } | 1436 } |
| 1437 | 1437 |
| 1438 | 1438 |
| 1439 LInstruction* LChunkBuilder::DoModByPowerOf2I(HMod* instr) { | 1439 LInstruction* LChunkBuilder::DoModByPowerOf2I(HMod* instr) { |
| 1440 ASSERT(instr->representation().IsSmiOrInteger32()); | 1440 DCHECK(instr->representation().IsSmiOrInteger32()); |
| 1441 ASSERT(instr->left()->representation().Equals(instr->representation())); | 1441 DCHECK(instr->left()->representation().Equals(instr->representation())); |
| 1442 ASSERT(instr->right()->representation().Equals(instr->representation())); | 1442 DCHECK(instr->right()->representation().Equals(instr->representation())); |
| 1443 LOperand* dividend = UseRegisterAtStart(instr->left()); | 1443 LOperand* dividend = UseRegisterAtStart(instr->left()); |
| 1444 int32_t divisor = instr->right()->GetInteger32Constant(); | 1444 int32_t divisor = instr->right()->GetInteger32Constant(); |
| 1445 LInstruction* result = DefineSameAsFirst(new(zone()) LModByPowerOf2I( | 1445 LInstruction* result = DefineSameAsFirst(new(zone()) LModByPowerOf2I( |
| 1446 dividend, divisor)); | 1446 dividend, divisor)); |
| 1447 if (instr->CheckFlag(HValue::kLeftCanBeNegative) && | 1447 if (instr->CheckFlag(HValue::kLeftCanBeNegative) && |
| 1448 instr->CheckFlag(HValue::kBailoutOnMinusZero)) { | 1448 instr->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 1449 result = AssignEnvironment(result); | 1449 result = AssignEnvironment(result); |
| 1450 } | 1450 } |
| 1451 return result; | 1451 return result; |
| 1452 } | 1452 } |
| 1453 | 1453 |
| 1454 | 1454 |
| 1455 LInstruction* LChunkBuilder::DoModByConstI(HMod* instr) { | 1455 LInstruction* LChunkBuilder::DoModByConstI(HMod* instr) { |
| 1456 ASSERT(instr->representation().IsSmiOrInteger32()); | 1456 DCHECK(instr->representation().IsSmiOrInteger32()); |
| 1457 ASSERT(instr->left()->representation().Equals(instr->representation())); | 1457 DCHECK(instr->left()->representation().Equals(instr->representation())); |
| 1458 ASSERT(instr->right()->representation().Equals(instr->representation())); | 1458 DCHECK(instr->right()->representation().Equals(instr->representation())); |
| 1459 LOperand* dividend = UseRegister(instr->left()); | 1459 LOperand* dividend = UseRegister(instr->left()); |
| 1460 int32_t divisor = instr->right()->GetInteger32Constant(); | 1460 int32_t divisor = instr->right()->GetInteger32Constant(); |
| 1461 LOperand* temp1 = FixedTemp(rax); | 1461 LOperand* temp1 = FixedTemp(rax); |
| 1462 LOperand* temp2 = FixedTemp(rdx); | 1462 LOperand* temp2 = FixedTemp(rdx); |
| 1463 LInstruction* result = DefineFixed(new(zone()) LModByConstI( | 1463 LInstruction* result = DefineFixed(new(zone()) LModByConstI( |
| 1464 dividend, divisor, temp1, temp2), rax); | 1464 dividend, divisor, temp1, temp2), rax); |
| 1465 if (divisor == 0 || instr->CheckFlag(HValue::kBailoutOnMinusZero)) { | 1465 if (divisor == 0 || instr->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 1466 result = AssignEnvironment(result); | 1466 result = AssignEnvironment(result); |
| 1467 } | 1467 } |
| 1468 return result; | 1468 return result; |
| 1469 } | 1469 } |
| 1470 | 1470 |
| 1471 | 1471 |
| 1472 LInstruction* LChunkBuilder::DoModI(HMod* instr) { | 1472 LInstruction* LChunkBuilder::DoModI(HMod* instr) { |
| 1473 ASSERT(instr->representation().IsSmiOrInteger32()); | 1473 DCHECK(instr->representation().IsSmiOrInteger32()); |
| 1474 ASSERT(instr->left()->representation().Equals(instr->representation())); | 1474 DCHECK(instr->left()->representation().Equals(instr->representation())); |
| 1475 ASSERT(instr->right()->representation().Equals(instr->representation())); | 1475 DCHECK(instr->right()->representation().Equals(instr->representation())); |
| 1476 LOperand* dividend = UseFixed(instr->left(), rax); | 1476 LOperand* dividend = UseFixed(instr->left(), rax); |
| 1477 LOperand* divisor = UseRegister(instr->right()); | 1477 LOperand* divisor = UseRegister(instr->right()); |
| 1478 LOperand* temp = FixedTemp(rdx); | 1478 LOperand* temp = FixedTemp(rdx); |
| 1479 LInstruction* result = DefineFixed(new(zone()) LModI( | 1479 LInstruction* result = DefineFixed(new(zone()) LModI( |
| 1480 dividend, divisor, temp), rdx); | 1480 dividend, divisor, temp), rdx); |
| 1481 if (instr->CheckFlag(HValue::kCanBeDivByZero) || | 1481 if (instr->CheckFlag(HValue::kCanBeDivByZero) || |
| 1482 instr->CheckFlag(HValue::kBailoutOnMinusZero)) { | 1482 instr->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 1483 result = AssignEnvironment(result); | 1483 result = AssignEnvironment(result); |
| 1484 } | 1484 } |
| 1485 return result; | 1485 return result; |
| (...skipping 12 matching lines...) Expand all Loading... |
| 1498 } else if (instr->representation().IsDouble()) { | 1498 } else if (instr->representation().IsDouble()) { |
| 1499 return DoArithmeticD(Token::MOD, instr); | 1499 return DoArithmeticD(Token::MOD, instr); |
| 1500 } else { | 1500 } else { |
| 1501 return DoArithmeticT(Token::MOD, instr); | 1501 return DoArithmeticT(Token::MOD, instr); |
| 1502 } | 1502 } |
| 1503 } | 1503 } |
| 1504 | 1504 |
| 1505 | 1505 |
| 1506 LInstruction* LChunkBuilder::DoMul(HMul* instr) { | 1506 LInstruction* LChunkBuilder::DoMul(HMul* instr) { |
| 1507 if (instr->representation().IsSmiOrInteger32()) { | 1507 if (instr->representation().IsSmiOrInteger32()) { |
| 1508 ASSERT(instr->left()->representation().Equals(instr->representation())); | 1508 DCHECK(instr->left()->representation().Equals(instr->representation())); |
| 1509 ASSERT(instr->right()->representation().Equals(instr->representation())); | 1509 DCHECK(instr->right()->representation().Equals(instr->representation())); |
| 1510 LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand()); | 1510 LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand()); |
| 1511 LOperand* right = UseOrConstant(instr->BetterRightOperand()); | 1511 LOperand* right = UseOrConstant(instr->BetterRightOperand()); |
| 1512 LMulI* mul = new(zone()) LMulI(left, right); | 1512 LMulI* mul = new(zone()) LMulI(left, right); |
| 1513 if (instr->CheckFlag(HValue::kCanOverflow) || | 1513 if (instr->CheckFlag(HValue::kCanOverflow) || |
| 1514 instr->CheckFlag(HValue::kBailoutOnMinusZero)) { | 1514 instr->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 1515 AssignEnvironment(mul); | 1515 AssignEnvironment(mul); |
| 1516 } | 1516 } |
| 1517 return DefineSameAsFirst(mul); | 1517 return DefineSameAsFirst(mul); |
| 1518 } else if (instr->representation().IsDouble()) { | 1518 } else if (instr->representation().IsDouble()) { |
| 1519 return DoArithmeticD(Token::MUL, instr); | 1519 return DoArithmeticD(Token::MUL, instr); |
| 1520 } else { | 1520 } else { |
| 1521 return DoArithmeticT(Token::MUL, instr); | 1521 return DoArithmeticT(Token::MUL, instr); |
| 1522 } | 1522 } |
| 1523 } | 1523 } |
| 1524 | 1524 |
| 1525 | 1525 |
| 1526 LInstruction* LChunkBuilder::DoSub(HSub* instr) { | 1526 LInstruction* LChunkBuilder::DoSub(HSub* instr) { |
| 1527 if (instr->representation().IsSmiOrInteger32()) { | 1527 if (instr->representation().IsSmiOrInteger32()) { |
| 1528 ASSERT(instr->left()->representation().Equals(instr->representation())); | 1528 DCHECK(instr->left()->representation().Equals(instr->representation())); |
| 1529 ASSERT(instr->right()->representation().Equals(instr->representation())); | 1529 DCHECK(instr->right()->representation().Equals(instr->representation())); |
| 1530 LOperand* left = UseRegisterAtStart(instr->left()); | 1530 LOperand* left = UseRegisterAtStart(instr->left()); |
| 1531 LOperand* right = UseOrConstantAtStart(instr->right()); | 1531 LOperand* right = UseOrConstantAtStart(instr->right()); |
| 1532 LSubI* sub = new(zone()) LSubI(left, right); | 1532 LSubI* sub = new(zone()) LSubI(left, right); |
| 1533 LInstruction* result = DefineSameAsFirst(sub); | 1533 LInstruction* result = DefineSameAsFirst(sub); |
| 1534 if (instr->CheckFlag(HValue::kCanOverflow)) { | 1534 if (instr->CheckFlag(HValue::kCanOverflow)) { |
| 1535 result = AssignEnvironment(result); | 1535 result = AssignEnvironment(result); |
| 1536 } | 1536 } |
| 1537 return result; | 1537 return result; |
| 1538 } else if (instr->representation().IsDouble()) { | 1538 } else if (instr->representation().IsDouble()) { |
| 1539 return DoArithmeticD(Token::SUB, instr); | 1539 return DoArithmeticD(Token::SUB, instr); |
| 1540 } else { | 1540 } else { |
| 1541 return DoArithmeticT(Token::SUB, instr); | 1541 return DoArithmeticT(Token::SUB, instr); |
| 1542 } | 1542 } |
| 1543 } | 1543 } |
| 1544 | 1544 |
| 1545 | 1545 |
| 1546 LInstruction* LChunkBuilder::DoAdd(HAdd* instr) { | 1546 LInstruction* LChunkBuilder::DoAdd(HAdd* instr) { |
| 1547 if (instr->representation().IsSmiOrInteger32()) { | 1547 if (instr->representation().IsSmiOrInteger32()) { |
| 1548 // Check to see if it would be advantageous to use an lea instruction rather | 1548 // Check to see if it would be advantageous to use an lea instruction rather |
| 1549 // than an add. This is the case when no overflow check is needed and there | 1549 // than an add. This is the case when no overflow check is needed and there |
| 1550 // are multiple uses of the add's inputs, so using a 3-register add will | 1550 // are multiple uses of the add's inputs, so using a 3-register add will |
| 1551 // preserve all input values for later uses. | 1551 // preserve all input values for later uses. |
| 1552 bool use_lea = LAddI::UseLea(instr); | 1552 bool use_lea = LAddI::UseLea(instr); |
| 1553 ASSERT(instr->left()->representation().Equals(instr->representation())); | 1553 DCHECK(instr->left()->representation().Equals(instr->representation())); |
| 1554 ASSERT(instr->right()->representation().Equals(instr->representation())); | 1554 DCHECK(instr->right()->representation().Equals(instr->representation())); |
| 1555 LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand()); | 1555 LOperand* left = UseRegisterAtStart(instr->BetterLeftOperand()); |
| 1556 HValue* right_candidate = instr->BetterRightOperand(); | 1556 HValue* right_candidate = instr->BetterRightOperand(); |
| 1557 LOperand* right; | 1557 LOperand* right; |
| 1558 if (SmiValuesAre32Bits() && instr->representation().IsSmi()) { | 1558 if (SmiValuesAre32Bits() && instr->representation().IsSmi()) { |
| 1559 // We cannot add a tagged immediate to a tagged value, | 1559 // We cannot add a tagged immediate to a tagged value, |
| 1560 // so we request it in a register. | 1560 // so we request it in a register. |
| 1561 right = UseRegisterAtStart(right_candidate); | 1561 right = UseRegisterAtStart(right_candidate); |
| 1562 } else { | 1562 } else { |
| 1563 right = use_lea ? UseRegisterOrConstantAtStart(right_candidate) | 1563 right = use_lea ? UseRegisterOrConstantAtStart(right_candidate) |
| 1564 : UseOrConstantAtStart(right_candidate); | 1564 : UseOrConstantAtStart(right_candidate); |
| 1565 } | 1565 } |
| 1566 LAddI* add = new(zone()) LAddI(left, right); | 1566 LAddI* add = new(zone()) LAddI(left, right); |
| 1567 bool can_overflow = instr->CheckFlag(HValue::kCanOverflow); | 1567 bool can_overflow = instr->CheckFlag(HValue::kCanOverflow); |
| 1568 LInstruction* result = use_lea ? DefineAsRegister(add) | 1568 LInstruction* result = use_lea ? DefineAsRegister(add) |
| 1569 : DefineSameAsFirst(add); | 1569 : DefineSameAsFirst(add); |
| 1570 if (can_overflow) { | 1570 if (can_overflow) { |
| 1571 result = AssignEnvironment(result); | 1571 result = AssignEnvironment(result); |
| 1572 } | 1572 } |
| 1573 return result; | 1573 return result; |
| 1574 } else if (instr->representation().IsExternal()) { | 1574 } else if (instr->representation().IsExternal()) { |
| 1575 ASSERT(instr->left()->representation().IsExternal()); | 1575 DCHECK(instr->left()->representation().IsExternal()); |
| 1576 ASSERT(instr->right()->representation().IsInteger32()); | 1576 DCHECK(instr->right()->representation().IsInteger32()); |
| 1577 ASSERT(!instr->CheckFlag(HValue::kCanOverflow)); | 1577 DCHECK(!instr->CheckFlag(HValue::kCanOverflow)); |
| 1578 bool use_lea = LAddI::UseLea(instr); | 1578 bool use_lea = LAddI::UseLea(instr); |
| 1579 LOperand* left = UseRegisterAtStart(instr->left()); | 1579 LOperand* left = UseRegisterAtStart(instr->left()); |
| 1580 HValue* right_candidate = instr->right(); | 1580 HValue* right_candidate = instr->right(); |
| 1581 LOperand* right = use_lea | 1581 LOperand* right = use_lea |
| 1582 ? UseRegisterOrConstantAtStart(right_candidate) | 1582 ? UseRegisterOrConstantAtStart(right_candidate) |
| 1583 : UseOrConstantAtStart(right_candidate); | 1583 : UseOrConstantAtStart(right_candidate); |
| 1584 LAddI* add = new(zone()) LAddI(left, right); | 1584 LAddI* add = new(zone()) LAddI(left, right); |
| 1585 LInstruction* result = use_lea | 1585 LInstruction* result = use_lea |
| 1586 ? DefineAsRegister(add) | 1586 ? DefineAsRegister(add) |
| 1587 : DefineSameAsFirst(add); | 1587 : DefineSameAsFirst(add); |
| 1588 return result; | 1588 return result; |
| 1589 } else if (instr->representation().IsDouble()) { | 1589 } else if (instr->representation().IsDouble()) { |
| 1590 return DoArithmeticD(Token::ADD, instr); | 1590 return DoArithmeticD(Token::ADD, instr); |
| 1591 } else { | 1591 } else { |
| 1592 return DoArithmeticT(Token::ADD, instr); | 1592 return DoArithmeticT(Token::ADD, instr); |
| 1593 } | 1593 } |
| 1594 return NULL; | 1594 return NULL; |
| 1595 } | 1595 } |
| 1596 | 1596 |
| 1597 | 1597 |
| 1598 LInstruction* LChunkBuilder::DoMathMinMax(HMathMinMax* instr) { | 1598 LInstruction* LChunkBuilder::DoMathMinMax(HMathMinMax* instr) { |
| 1599 LOperand* left = NULL; | 1599 LOperand* left = NULL; |
| 1600 LOperand* right = NULL; | 1600 LOperand* right = NULL; |
| 1601 ASSERT(instr->left()->representation().Equals(instr->representation())); | 1601 DCHECK(instr->left()->representation().Equals(instr->representation())); |
| 1602 ASSERT(instr->right()->representation().Equals(instr->representation())); | 1602 DCHECK(instr->right()->representation().Equals(instr->representation())); |
| 1603 if (instr->representation().IsSmi()) { | 1603 if (instr->representation().IsSmi()) { |
| 1604 left = UseRegisterAtStart(instr->BetterLeftOperand()); | 1604 left = UseRegisterAtStart(instr->BetterLeftOperand()); |
| 1605 right = UseAtStart(instr->BetterRightOperand()); | 1605 right = UseAtStart(instr->BetterRightOperand()); |
| 1606 } else if (instr->representation().IsInteger32()) { | 1606 } else if (instr->representation().IsInteger32()) { |
| 1607 left = UseRegisterAtStart(instr->BetterLeftOperand()); | 1607 left = UseRegisterAtStart(instr->BetterLeftOperand()); |
| 1608 right = UseOrConstantAtStart(instr->BetterRightOperand()); | 1608 right = UseOrConstantAtStart(instr->BetterRightOperand()); |
| 1609 } else { | 1609 } else { |
| 1610 ASSERT(instr->representation().IsDouble()); | 1610 DCHECK(instr->representation().IsDouble()); |
| 1611 left = UseRegisterAtStart(instr->left()); | 1611 left = UseRegisterAtStart(instr->left()); |
| 1612 right = UseRegisterAtStart(instr->right()); | 1612 right = UseRegisterAtStart(instr->right()); |
| 1613 } | 1613 } |
| 1614 LMathMinMax* minmax = new(zone()) LMathMinMax(left, right); | 1614 LMathMinMax* minmax = new(zone()) LMathMinMax(left, right); |
| 1615 return DefineSameAsFirst(minmax); | 1615 return DefineSameAsFirst(minmax); |
| 1616 } | 1616 } |
| 1617 | 1617 |
| 1618 | 1618 |
| 1619 LInstruction* LChunkBuilder::DoPower(HPower* instr) { | 1619 LInstruction* LChunkBuilder::DoPower(HPower* instr) { |
| 1620 ASSERT(instr->representation().IsDouble()); | 1620 DCHECK(instr->representation().IsDouble()); |
| 1621 // We call a C function for double power. It can't trigger a GC. | 1621 // We call a C function for double power. It can't trigger a GC. |
| 1622 // We need to use fixed result register for the call. | 1622 // We need to use fixed result register for the call. |
| 1623 Representation exponent_type = instr->right()->representation(); | 1623 Representation exponent_type = instr->right()->representation(); |
| 1624 ASSERT(instr->left()->representation().IsDouble()); | 1624 DCHECK(instr->left()->representation().IsDouble()); |
| 1625 LOperand* left = UseFixedDouble(instr->left(), xmm2); | 1625 LOperand* left = UseFixedDouble(instr->left(), xmm2); |
| 1626 LOperand* right = exponent_type.IsDouble() ? | 1626 LOperand* right = exponent_type.IsDouble() ? |
| 1627 UseFixedDouble(instr->right(), xmm1) : UseFixed(instr->right(), rdx); | 1627 UseFixedDouble(instr->right(), xmm1) : UseFixed(instr->right(), rdx); |
| 1628 LPower* result = new(zone()) LPower(left, right); | 1628 LPower* result = new(zone()) LPower(left, right); |
| 1629 return MarkAsCall(DefineFixedDouble(result, xmm3), instr, | 1629 return MarkAsCall(DefineFixedDouble(result, xmm3), instr, |
| 1630 CAN_DEOPTIMIZE_EAGERLY); | 1630 CAN_DEOPTIMIZE_EAGERLY); |
| 1631 } | 1631 } |
| 1632 | 1632 |
| 1633 | 1633 |
| 1634 LInstruction* LChunkBuilder::DoCompareGeneric(HCompareGeneric* instr) { | 1634 LInstruction* LChunkBuilder::DoCompareGeneric(HCompareGeneric* instr) { |
| 1635 ASSERT(instr->left()->representation().IsTagged()); | 1635 DCHECK(instr->left()->representation().IsTagged()); |
| 1636 ASSERT(instr->right()->representation().IsTagged()); | 1636 DCHECK(instr->right()->representation().IsTagged()); |
| 1637 LOperand* context = UseFixed(instr->context(), rsi); | 1637 LOperand* context = UseFixed(instr->context(), rsi); |
| 1638 LOperand* left = UseFixed(instr->left(), rdx); | 1638 LOperand* left = UseFixed(instr->left(), rdx); |
| 1639 LOperand* right = UseFixed(instr->right(), rax); | 1639 LOperand* right = UseFixed(instr->right(), rax); |
| 1640 LCmpT* result = new(zone()) LCmpT(context, left, right); | 1640 LCmpT* result = new(zone()) LCmpT(context, left, right); |
| 1641 return MarkAsCall(DefineFixed(result, rax), instr); | 1641 return MarkAsCall(DefineFixed(result, rax), instr); |
| 1642 } | 1642 } |
| 1643 | 1643 |
| 1644 | 1644 |
| 1645 LInstruction* LChunkBuilder::DoCompareNumericAndBranch( | 1645 LInstruction* LChunkBuilder::DoCompareNumericAndBranch( |
| 1646 HCompareNumericAndBranch* instr) { | 1646 HCompareNumericAndBranch* instr) { |
| 1647 Representation r = instr->representation(); | 1647 Representation r = instr->representation(); |
| 1648 if (r.IsSmiOrInteger32()) { | 1648 if (r.IsSmiOrInteger32()) { |
| 1649 ASSERT(instr->left()->representation().Equals(r)); | 1649 DCHECK(instr->left()->representation().Equals(r)); |
| 1650 ASSERT(instr->right()->representation().Equals(r)); | 1650 DCHECK(instr->right()->representation().Equals(r)); |
| 1651 LOperand* left = UseRegisterOrConstantAtStart(instr->left()); | 1651 LOperand* left = UseRegisterOrConstantAtStart(instr->left()); |
| 1652 LOperand* right = UseOrConstantAtStart(instr->right()); | 1652 LOperand* right = UseOrConstantAtStart(instr->right()); |
| 1653 return new(zone()) LCompareNumericAndBranch(left, right); | 1653 return new(zone()) LCompareNumericAndBranch(left, right); |
| 1654 } else { | 1654 } else { |
| 1655 ASSERT(r.IsDouble()); | 1655 DCHECK(r.IsDouble()); |
| 1656 ASSERT(instr->left()->representation().IsDouble()); | 1656 DCHECK(instr->left()->representation().IsDouble()); |
| 1657 ASSERT(instr->right()->representation().IsDouble()); | 1657 DCHECK(instr->right()->representation().IsDouble()); |
| 1658 LOperand* left; | 1658 LOperand* left; |
| 1659 LOperand* right; | 1659 LOperand* right; |
| 1660 if (instr->left()->IsConstant() && instr->right()->IsConstant()) { | 1660 if (instr->left()->IsConstant() && instr->right()->IsConstant()) { |
| 1661 left = UseRegisterOrConstantAtStart(instr->left()); | 1661 left = UseRegisterOrConstantAtStart(instr->left()); |
| 1662 right = UseRegisterOrConstantAtStart(instr->right()); | 1662 right = UseRegisterOrConstantAtStart(instr->right()); |
| 1663 } else { | 1663 } else { |
| 1664 left = UseRegisterAtStart(instr->left()); | 1664 left = UseRegisterAtStart(instr->left()); |
| 1665 right = UseRegisterAtStart(instr->right()); | 1665 right = UseRegisterAtStart(instr->right()); |
| 1666 } | 1666 } |
| 1667 return new(zone()) LCompareNumericAndBranch(left, right); | 1667 return new(zone()) LCompareNumericAndBranch(left, right); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 1685 | 1685 |
| 1686 | 1686 |
| 1687 LInstruction* LChunkBuilder::DoCompareMinusZeroAndBranch( | 1687 LInstruction* LChunkBuilder::DoCompareMinusZeroAndBranch( |
| 1688 HCompareMinusZeroAndBranch* instr) { | 1688 HCompareMinusZeroAndBranch* instr) { |
| 1689 LOperand* value = UseRegister(instr->value()); | 1689 LOperand* value = UseRegister(instr->value()); |
| 1690 return new(zone()) LCompareMinusZeroAndBranch(value); | 1690 return new(zone()) LCompareMinusZeroAndBranch(value); |
| 1691 } | 1691 } |
| 1692 | 1692 |
| 1693 | 1693 |
| 1694 LInstruction* LChunkBuilder::DoIsObjectAndBranch(HIsObjectAndBranch* instr) { | 1694 LInstruction* LChunkBuilder::DoIsObjectAndBranch(HIsObjectAndBranch* instr) { |
| 1695 ASSERT(instr->value()->representation().IsTagged()); | 1695 DCHECK(instr->value()->representation().IsTagged()); |
| 1696 return new(zone()) LIsObjectAndBranch(UseRegisterAtStart(instr->value())); | 1696 return new(zone()) LIsObjectAndBranch(UseRegisterAtStart(instr->value())); |
| 1697 } | 1697 } |
| 1698 | 1698 |
| 1699 | 1699 |
| 1700 LInstruction* LChunkBuilder::DoIsStringAndBranch(HIsStringAndBranch* instr) { | 1700 LInstruction* LChunkBuilder::DoIsStringAndBranch(HIsStringAndBranch* instr) { |
| 1701 ASSERT(instr->value()->representation().IsTagged()); | 1701 DCHECK(instr->value()->representation().IsTagged()); |
| 1702 LOperand* value = UseRegisterAtStart(instr->value()); | 1702 LOperand* value = UseRegisterAtStart(instr->value()); |
| 1703 LOperand* temp = TempRegister(); | 1703 LOperand* temp = TempRegister(); |
| 1704 return new(zone()) LIsStringAndBranch(value, temp); | 1704 return new(zone()) LIsStringAndBranch(value, temp); |
| 1705 } | 1705 } |
| 1706 | 1706 |
| 1707 | 1707 |
| 1708 LInstruction* LChunkBuilder::DoIsSmiAndBranch(HIsSmiAndBranch* instr) { | 1708 LInstruction* LChunkBuilder::DoIsSmiAndBranch(HIsSmiAndBranch* instr) { |
| 1709 ASSERT(instr->value()->representation().IsTagged()); | 1709 DCHECK(instr->value()->representation().IsTagged()); |
| 1710 return new(zone()) LIsSmiAndBranch(Use(instr->value())); | 1710 return new(zone()) LIsSmiAndBranch(Use(instr->value())); |
| 1711 } | 1711 } |
| 1712 | 1712 |
| 1713 | 1713 |
| 1714 LInstruction* LChunkBuilder::DoIsUndetectableAndBranch( | 1714 LInstruction* LChunkBuilder::DoIsUndetectableAndBranch( |
| 1715 HIsUndetectableAndBranch* instr) { | 1715 HIsUndetectableAndBranch* instr) { |
| 1716 ASSERT(instr->value()->representation().IsTagged()); | 1716 DCHECK(instr->value()->representation().IsTagged()); |
| 1717 LOperand* value = UseRegisterAtStart(instr->value()); | 1717 LOperand* value = UseRegisterAtStart(instr->value()); |
| 1718 LOperand* temp = TempRegister(); | 1718 LOperand* temp = TempRegister(); |
| 1719 return new(zone()) LIsUndetectableAndBranch(value, temp); | 1719 return new(zone()) LIsUndetectableAndBranch(value, temp); |
| 1720 } | 1720 } |
| 1721 | 1721 |
| 1722 | 1722 |
| 1723 LInstruction* LChunkBuilder::DoStringCompareAndBranch( | 1723 LInstruction* LChunkBuilder::DoStringCompareAndBranch( |
| 1724 HStringCompareAndBranch* instr) { | 1724 HStringCompareAndBranch* instr) { |
| 1725 | 1725 |
| 1726 ASSERT(instr->left()->representation().IsTagged()); | 1726 DCHECK(instr->left()->representation().IsTagged()); |
| 1727 ASSERT(instr->right()->representation().IsTagged()); | 1727 DCHECK(instr->right()->representation().IsTagged()); |
| 1728 LOperand* context = UseFixed(instr->context(), rsi); | 1728 LOperand* context = UseFixed(instr->context(), rsi); |
| 1729 LOperand* left = UseFixed(instr->left(), rdx); | 1729 LOperand* left = UseFixed(instr->left(), rdx); |
| 1730 LOperand* right = UseFixed(instr->right(), rax); | 1730 LOperand* right = UseFixed(instr->right(), rax); |
| 1731 LStringCompareAndBranch* result = | 1731 LStringCompareAndBranch* result = |
| 1732 new(zone()) LStringCompareAndBranch(context, left, right); | 1732 new(zone()) LStringCompareAndBranch(context, left, right); |
| 1733 | 1733 |
| 1734 return MarkAsCall(result, instr); | 1734 return MarkAsCall(result, instr); |
| 1735 } | 1735 } |
| 1736 | 1736 |
| 1737 | 1737 |
| 1738 LInstruction* LChunkBuilder::DoHasInstanceTypeAndBranch( | 1738 LInstruction* LChunkBuilder::DoHasInstanceTypeAndBranch( |
| 1739 HHasInstanceTypeAndBranch* instr) { | 1739 HHasInstanceTypeAndBranch* instr) { |
| 1740 ASSERT(instr->value()->representation().IsTagged()); | 1740 DCHECK(instr->value()->representation().IsTagged()); |
| 1741 LOperand* value = UseRegisterAtStart(instr->value()); | 1741 LOperand* value = UseRegisterAtStart(instr->value()); |
| 1742 return new(zone()) LHasInstanceTypeAndBranch(value); | 1742 return new(zone()) LHasInstanceTypeAndBranch(value); |
| 1743 } | 1743 } |
| 1744 | 1744 |
| 1745 | 1745 |
| 1746 LInstruction* LChunkBuilder::DoGetCachedArrayIndex( | 1746 LInstruction* LChunkBuilder::DoGetCachedArrayIndex( |
| 1747 HGetCachedArrayIndex* instr) { | 1747 HGetCachedArrayIndex* instr) { |
| 1748 ASSERT(instr->value()->representation().IsTagged()); | 1748 DCHECK(instr->value()->representation().IsTagged()); |
| 1749 LOperand* value = UseRegisterAtStart(instr->value()); | 1749 LOperand* value = UseRegisterAtStart(instr->value()); |
| 1750 | 1750 |
| 1751 return DefineAsRegister(new(zone()) LGetCachedArrayIndex(value)); | 1751 return DefineAsRegister(new(zone()) LGetCachedArrayIndex(value)); |
| 1752 } | 1752 } |
| 1753 | 1753 |
| 1754 | 1754 |
| 1755 LInstruction* LChunkBuilder::DoHasCachedArrayIndexAndBranch( | 1755 LInstruction* LChunkBuilder::DoHasCachedArrayIndexAndBranch( |
| 1756 HHasCachedArrayIndexAndBranch* instr) { | 1756 HHasCachedArrayIndexAndBranch* instr) { |
| 1757 ASSERT(instr->value()->representation().IsTagged()); | 1757 DCHECK(instr->value()->representation().IsTagged()); |
| 1758 LOperand* value = UseRegisterAtStart(instr->value()); | 1758 LOperand* value = UseRegisterAtStart(instr->value()); |
| 1759 return new(zone()) LHasCachedArrayIndexAndBranch(value); | 1759 return new(zone()) LHasCachedArrayIndexAndBranch(value); |
| 1760 } | 1760 } |
| 1761 | 1761 |
| 1762 | 1762 |
| 1763 LInstruction* LChunkBuilder::DoClassOfTestAndBranch( | 1763 LInstruction* LChunkBuilder::DoClassOfTestAndBranch( |
| 1764 HClassOfTestAndBranch* instr) { | 1764 HClassOfTestAndBranch* instr) { |
| 1765 LOperand* value = UseRegister(instr->value()); | 1765 LOperand* value = UseRegister(instr->value()); |
| 1766 return new(zone()) LClassOfTestAndBranch(value, | 1766 return new(zone()) LClassOfTestAndBranch(value, |
| 1767 TempRegister(), | 1767 TempRegister(), |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1865 LInstruction* result = DefineAsRegister(new(zone()) LNumberUntagD(value)); | 1865 LInstruction* result = DefineAsRegister(new(zone()) LNumberUntagD(value)); |
| 1866 if (!val->representation().IsSmi()) result = AssignEnvironment(result); | 1866 if (!val->representation().IsSmi()) result = AssignEnvironment(result); |
| 1867 return result; | 1867 return result; |
| 1868 } else if (to.IsSmi()) { | 1868 } else if (to.IsSmi()) { |
| 1869 LOperand* value = UseRegister(val); | 1869 LOperand* value = UseRegister(val); |
| 1870 if (val->type().IsSmi()) { | 1870 if (val->type().IsSmi()) { |
| 1871 return DefineSameAsFirst(new(zone()) LDummyUse(value)); | 1871 return DefineSameAsFirst(new(zone()) LDummyUse(value)); |
| 1872 } | 1872 } |
| 1873 return AssignEnvironment(DefineSameAsFirst(new(zone()) LCheckSmi(value))); | 1873 return AssignEnvironment(DefineSameAsFirst(new(zone()) LCheckSmi(value))); |
| 1874 } else { | 1874 } else { |
| 1875 ASSERT(to.IsInteger32()); | 1875 DCHECK(to.IsInteger32()); |
| 1876 if (val->type().IsSmi() || val->representation().IsSmi()) { | 1876 if (val->type().IsSmi() || val->representation().IsSmi()) { |
| 1877 LOperand* value = UseRegister(val); | 1877 LOperand* value = UseRegister(val); |
| 1878 return DefineSameAsFirst(new(zone()) LSmiUntag(value, false)); | 1878 return DefineSameAsFirst(new(zone()) LSmiUntag(value, false)); |
| 1879 } else { | 1879 } else { |
| 1880 LOperand* value = UseRegister(val); | 1880 LOperand* value = UseRegister(val); |
| 1881 bool truncating = instr->CanTruncateToInt32(); | 1881 bool truncating = instr->CanTruncateToInt32(); |
| 1882 LOperand* xmm_temp = truncating ? NULL : FixedTemp(xmm1); | 1882 LOperand* xmm_temp = truncating ? NULL : FixedTemp(xmm1); |
| 1883 LInstruction* result = | 1883 LInstruction* result = |
| 1884 DefineSameAsFirst(new(zone()) LTaggedToI(value, xmm_temp)); | 1884 DefineSameAsFirst(new(zone()) LTaggedToI(value, xmm_temp)); |
| 1885 if (!val->representation().IsSmi()) result = AssignEnvironment(result); | 1885 if (!val->representation().IsSmi()) result = AssignEnvironment(result); |
| 1886 return result; | 1886 return result; |
| 1887 } | 1887 } |
| 1888 } | 1888 } |
| 1889 } else if (from.IsDouble()) { | 1889 } else if (from.IsDouble()) { |
| 1890 if (to.IsTagged()) { | 1890 if (to.IsTagged()) { |
| 1891 info()->MarkAsDeferredCalling(); | 1891 info()->MarkAsDeferredCalling(); |
| 1892 LOperand* value = UseRegister(val); | 1892 LOperand* value = UseRegister(val); |
| 1893 LOperand* temp = TempRegister(); | 1893 LOperand* temp = TempRegister(); |
| 1894 LUnallocated* result_temp = TempRegister(); | 1894 LUnallocated* result_temp = TempRegister(); |
| 1895 LNumberTagD* result = new(zone()) LNumberTagD(value, temp); | 1895 LNumberTagD* result = new(zone()) LNumberTagD(value, temp); |
| 1896 return AssignPointerMap(Define(result, result_temp)); | 1896 return AssignPointerMap(Define(result, result_temp)); |
| 1897 } else if (to.IsSmi()) { | 1897 } else if (to.IsSmi()) { |
| 1898 LOperand* value = UseRegister(val); | 1898 LOperand* value = UseRegister(val); |
| 1899 return AssignEnvironment( | 1899 return AssignEnvironment( |
| 1900 DefineAsRegister(new(zone()) LDoubleToSmi(value))); | 1900 DefineAsRegister(new(zone()) LDoubleToSmi(value))); |
| 1901 } else { | 1901 } else { |
| 1902 ASSERT(to.IsInteger32()); | 1902 DCHECK(to.IsInteger32()); |
| 1903 LOperand* value = UseRegister(val); | 1903 LOperand* value = UseRegister(val); |
| 1904 LInstruction* result = DefineAsRegister(new(zone()) LDoubleToI(value)); | 1904 LInstruction* result = DefineAsRegister(new(zone()) LDoubleToI(value)); |
| 1905 if (!instr->CanTruncateToInt32()) result = AssignEnvironment(result); | 1905 if (!instr->CanTruncateToInt32()) result = AssignEnvironment(result); |
| 1906 return result; | 1906 return result; |
| 1907 } | 1907 } |
| 1908 } else if (from.IsInteger32()) { | 1908 } else if (from.IsInteger32()) { |
| 1909 info()->MarkAsDeferredCalling(); | 1909 info()->MarkAsDeferredCalling(); |
| 1910 if (to.IsTagged()) { | 1910 if (to.IsTagged()) { |
| 1911 if (!instr->CheckFlag(HValue::kCanOverflow)) { | 1911 if (!instr->CheckFlag(HValue::kCanOverflow)) { |
| 1912 LOperand* value = UseRegister(val); | 1912 LOperand* value = UseRegister(val); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 1925 return AssignPointerMap(DefineSameAsFirst(result)); | 1925 return AssignPointerMap(DefineSameAsFirst(result)); |
| 1926 } | 1926 } |
| 1927 } else if (to.IsSmi()) { | 1927 } else if (to.IsSmi()) { |
| 1928 LOperand* value = UseRegister(val); | 1928 LOperand* value = UseRegister(val); |
| 1929 LInstruction* result = DefineAsRegister(new(zone()) LSmiTag(value)); | 1929 LInstruction* result = DefineAsRegister(new(zone()) LSmiTag(value)); |
| 1930 if (instr->CheckFlag(HValue::kCanOverflow)) { | 1930 if (instr->CheckFlag(HValue::kCanOverflow)) { |
| 1931 result = AssignEnvironment(result); | 1931 result = AssignEnvironment(result); |
| 1932 } | 1932 } |
| 1933 return result; | 1933 return result; |
| 1934 } else { | 1934 } else { |
| 1935 ASSERT(to.IsDouble()); | 1935 DCHECK(to.IsDouble()); |
| 1936 if (val->CheckFlag(HInstruction::kUint32)) { | 1936 if (val->CheckFlag(HInstruction::kUint32)) { |
| 1937 return DefineAsRegister(new(zone()) LUint32ToDouble(UseRegister(val))); | 1937 return DefineAsRegister(new(zone()) LUint32ToDouble(UseRegister(val))); |
| 1938 } else { | 1938 } else { |
| 1939 LOperand* value = Use(val); | 1939 LOperand* value = Use(val); |
| 1940 return DefineAsRegister(new(zone()) LInteger32ToDouble(value)); | 1940 return DefineAsRegister(new(zone()) LInteger32ToDouble(value)); |
| 1941 } | 1941 } |
| 1942 } | 1942 } |
| 1943 } | 1943 } |
| 1944 UNREACHABLE(); | 1944 UNREACHABLE(); |
| 1945 return NULL; | 1945 return NULL; |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1989 | 1989 |
| 1990 LInstruction* LChunkBuilder::DoClampToUint8(HClampToUint8* instr) { | 1990 LInstruction* LChunkBuilder::DoClampToUint8(HClampToUint8* instr) { |
| 1991 HValue* value = instr->value(); | 1991 HValue* value = instr->value(); |
| 1992 Representation input_rep = value->representation(); | 1992 Representation input_rep = value->representation(); |
| 1993 LOperand* reg = UseRegister(value); | 1993 LOperand* reg = UseRegister(value); |
| 1994 if (input_rep.IsDouble()) { | 1994 if (input_rep.IsDouble()) { |
| 1995 return DefineAsRegister(new(zone()) LClampDToUint8(reg)); | 1995 return DefineAsRegister(new(zone()) LClampDToUint8(reg)); |
| 1996 } else if (input_rep.IsInteger32()) { | 1996 } else if (input_rep.IsInteger32()) { |
| 1997 return DefineSameAsFirst(new(zone()) LClampIToUint8(reg)); | 1997 return DefineSameAsFirst(new(zone()) LClampIToUint8(reg)); |
| 1998 } else { | 1998 } else { |
| 1999 ASSERT(input_rep.IsSmiOrTagged()); | 1999 DCHECK(input_rep.IsSmiOrTagged()); |
| 2000 // Register allocator doesn't (yet) support allocation of double | 2000 // Register allocator doesn't (yet) support allocation of double |
| 2001 // temps. Reserve xmm1 explicitly. | 2001 // temps. Reserve xmm1 explicitly. |
| 2002 LClampTToUint8* result = new(zone()) LClampTToUint8(reg, | 2002 LClampTToUint8* result = new(zone()) LClampTToUint8(reg, |
| 2003 FixedTemp(xmm1)); | 2003 FixedTemp(xmm1)); |
| 2004 return AssignEnvironment(DefineSameAsFirst(result)); | 2004 return AssignEnvironment(DefineSameAsFirst(result)); |
| 2005 } | 2005 } |
| 2006 } | 2006 } |
| 2007 | 2007 |
| 2008 | 2008 |
| 2009 LInstruction* LChunkBuilder::DoDoubleBits(HDoubleBits* instr) { | 2009 LInstruction* LChunkBuilder::DoDoubleBits(HDoubleBits* instr) { |
| 2010 HValue* value = instr->value(); | 2010 HValue* value = instr->value(); |
| 2011 ASSERT(value->representation().IsDouble()); | 2011 DCHECK(value->representation().IsDouble()); |
| 2012 return DefineAsRegister(new(zone()) LDoubleBits(UseRegister(value))); | 2012 return DefineAsRegister(new(zone()) LDoubleBits(UseRegister(value))); |
| 2013 } | 2013 } |
| 2014 | 2014 |
| 2015 | 2015 |
| 2016 LInstruction* LChunkBuilder::DoConstructDouble(HConstructDouble* instr) { | 2016 LInstruction* LChunkBuilder::DoConstructDouble(HConstructDouble* instr) { |
| 2017 LOperand* lo = UseRegister(instr->lo()); | 2017 LOperand* lo = UseRegister(instr->lo()); |
| 2018 LOperand* hi = UseRegister(instr->hi()); | 2018 LOperand* hi = UseRegister(instr->hi()); |
| 2019 return DefineAsRegister(new(zone()) LConstructDouble(hi, lo)); | 2019 return DefineAsRegister(new(zone()) LConstructDouble(hi, lo)); |
| 2020 } | 2020 } |
| 2021 | 2021 |
| (...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2152 LInstruction* LChunkBuilder::DoLoadRoot(HLoadRoot* instr) { | 2152 LInstruction* LChunkBuilder::DoLoadRoot(HLoadRoot* instr) { |
| 2153 return DefineAsRegister(new(zone()) LLoadRoot); | 2153 return DefineAsRegister(new(zone()) LLoadRoot); |
| 2154 } | 2154 } |
| 2155 | 2155 |
| 2156 | 2156 |
| 2157 void LChunkBuilder::FindDehoistedKeyDefinitions(HValue* candidate) { | 2157 void LChunkBuilder::FindDehoistedKeyDefinitions(HValue* candidate) { |
| 2158 // We sign extend the dehoisted key at the definition point when the pointer | 2158 // We sign extend the dehoisted key at the definition point when the pointer |
| 2159 // size is 64-bit. For x32 port, we sign extend the dehoisted key at the use | 2159 // size is 64-bit. For x32 port, we sign extend the dehoisted key at the use |
| 2160 // points and should not invoke this function. We can't use STATIC_ASSERT | 2160 // points and should not invoke this function. We can't use STATIC_ASSERT |
| 2161 // here as the pointer size is 32-bit for x32. | 2161 // here as the pointer size is 32-bit for x32. |
| 2162 ASSERT(kPointerSize == kInt64Size); | 2162 DCHECK(kPointerSize == kInt64Size); |
| 2163 BitVector* dehoisted_key_ids = chunk_->GetDehoistedKeyIds(); | 2163 BitVector* dehoisted_key_ids = chunk_->GetDehoistedKeyIds(); |
| 2164 if (dehoisted_key_ids->Contains(candidate->id())) return; | 2164 if (dehoisted_key_ids->Contains(candidate->id())) return; |
| 2165 dehoisted_key_ids->Add(candidate->id()); | 2165 dehoisted_key_ids->Add(candidate->id()); |
| 2166 if (!candidate->IsPhi()) return; | 2166 if (!candidate->IsPhi()) return; |
| 2167 for (int i = 0; i < candidate->OperandCount(); ++i) { | 2167 for (int i = 0; i < candidate->OperandCount(); ++i) { |
| 2168 FindDehoistedKeyDefinitions(candidate->OperandAt(i)); | 2168 FindDehoistedKeyDefinitions(candidate->OperandAt(i)); |
| 2169 } | 2169 } |
| 2170 } | 2170 } |
| 2171 | 2171 |
| 2172 | 2172 |
| 2173 LInstruction* LChunkBuilder::DoLoadKeyed(HLoadKeyed* instr) { | 2173 LInstruction* LChunkBuilder::DoLoadKeyed(HLoadKeyed* instr) { |
| 2174 ASSERT((kPointerSize == kInt64Size && | 2174 DCHECK((kPointerSize == kInt64Size && |
| 2175 instr->key()->representation().IsInteger32()) || | 2175 instr->key()->representation().IsInteger32()) || |
| 2176 (kPointerSize == kInt32Size && | 2176 (kPointerSize == kInt32Size && |
| 2177 instr->key()->representation().IsSmiOrInteger32())); | 2177 instr->key()->representation().IsSmiOrInteger32())); |
| 2178 ElementsKind elements_kind = instr->elements_kind(); | 2178 ElementsKind elements_kind = instr->elements_kind(); |
| 2179 LOperand* key = NULL; | 2179 LOperand* key = NULL; |
| 2180 LInstruction* result = NULL; | 2180 LInstruction* result = NULL; |
| 2181 | 2181 |
| 2182 if (kPointerSize == kInt64Size) { | 2182 if (kPointerSize == kInt64Size) { |
| 2183 key = UseRegisterOrConstantAtStart(instr->key()); | 2183 key = UseRegisterOrConstantAtStart(instr->key()); |
| 2184 } else { | 2184 } else { |
| 2185 bool clobbers_key = ExternalArrayOpRequiresTemp( | 2185 bool clobbers_key = ExternalArrayOpRequiresTemp( |
| 2186 instr->key()->representation(), elements_kind); | 2186 instr->key()->representation(), elements_kind); |
| 2187 key = clobbers_key | 2187 key = clobbers_key |
| 2188 ? UseTempRegister(instr->key()) | 2188 ? UseTempRegister(instr->key()) |
| 2189 : UseRegisterOrConstantAtStart(instr->key()); | 2189 : UseRegisterOrConstantAtStart(instr->key()); |
| 2190 } | 2190 } |
| 2191 | 2191 |
| 2192 if ((kPointerSize == kInt64Size) && instr->IsDehoisted()) { | 2192 if ((kPointerSize == kInt64Size) && instr->IsDehoisted()) { |
| 2193 FindDehoistedKeyDefinitions(instr->key()); | 2193 FindDehoistedKeyDefinitions(instr->key()); |
| 2194 } | 2194 } |
| 2195 | 2195 |
| 2196 if (!instr->is_typed_elements()) { | 2196 if (!instr->is_typed_elements()) { |
| 2197 LOperand* obj = UseRegisterAtStart(instr->elements()); | 2197 LOperand* obj = UseRegisterAtStart(instr->elements()); |
| 2198 result = DefineAsRegister(new(zone()) LLoadKeyed(obj, key)); | 2198 result = DefineAsRegister(new(zone()) LLoadKeyed(obj, key)); |
| 2199 } else { | 2199 } else { |
| 2200 ASSERT( | 2200 DCHECK( |
| 2201 (instr->representation().IsInteger32() && | 2201 (instr->representation().IsInteger32() && |
| 2202 !(IsDoubleOrFloatElementsKind(elements_kind))) || | 2202 !(IsDoubleOrFloatElementsKind(elements_kind))) || |
| 2203 (instr->representation().IsDouble() && | 2203 (instr->representation().IsDouble() && |
| 2204 (IsDoubleOrFloatElementsKind(elements_kind)))); | 2204 (IsDoubleOrFloatElementsKind(elements_kind)))); |
| 2205 LOperand* backing_store = UseRegister(instr->elements()); | 2205 LOperand* backing_store = UseRegister(instr->elements()); |
| 2206 result = DefineAsRegister(new(zone()) LLoadKeyed(backing_store, key)); | 2206 result = DefineAsRegister(new(zone()) LLoadKeyed(backing_store, key)); |
| 2207 } | 2207 } |
| 2208 | 2208 |
| 2209 if ((instr->is_external() || instr->is_fixed_typed_array()) ? | 2209 if ((instr->is_external() || instr->is_fixed_typed_array()) ? |
| 2210 // see LCodeGen::DoLoadKeyedExternalArray | 2210 // see LCodeGen::DoLoadKeyedExternalArray |
| (...skipping 25 matching lines...) Expand all Loading... |
| 2236 | 2236 |
| 2237 | 2237 |
| 2238 LInstruction* LChunkBuilder::DoStoreKeyed(HStoreKeyed* instr) { | 2238 LInstruction* LChunkBuilder::DoStoreKeyed(HStoreKeyed* instr) { |
| 2239 ElementsKind elements_kind = instr->elements_kind(); | 2239 ElementsKind elements_kind = instr->elements_kind(); |
| 2240 | 2240 |
| 2241 if ((kPointerSize == kInt64Size) && instr->IsDehoisted()) { | 2241 if ((kPointerSize == kInt64Size) && instr->IsDehoisted()) { |
| 2242 FindDehoistedKeyDefinitions(instr->key()); | 2242 FindDehoistedKeyDefinitions(instr->key()); |
| 2243 } | 2243 } |
| 2244 | 2244 |
| 2245 if (!instr->is_typed_elements()) { | 2245 if (!instr->is_typed_elements()) { |
| 2246 ASSERT(instr->elements()->representation().IsTagged()); | 2246 DCHECK(instr->elements()->representation().IsTagged()); |
| 2247 bool needs_write_barrier = instr->NeedsWriteBarrier(); | 2247 bool needs_write_barrier = instr->NeedsWriteBarrier(); |
| 2248 LOperand* object = NULL; | 2248 LOperand* object = NULL; |
| 2249 LOperand* key = NULL; | 2249 LOperand* key = NULL; |
| 2250 LOperand* val = NULL; | 2250 LOperand* val = NULL; |
| 2251 | 2251 |
| 2252 Representation value_representation = instr->value()->representation(); | 2252 Representation value_representation = instr->value()->representation(); |
| 2253 if (value_representation.IsDouble()) { | 2253 if (value_representation.IsDouble()) { |
| 2254 object = UseRegisterAtStart(instr->elements()); | 2254 object = UseRegisterAtStart(instr->elements()); |
| 2255 val = UseRegisterAtStart(instr->value()); | 2255 val = UseRegisterAtStart(instr->value()); |
| 2256 key = UseRegisterOrConstantAtStart(instr->key()); | 2256 key = UseRegisterOrConstantAtStart(instr->key()); |
| 2257 } else { | 2257 } else { |
| 2258 ASSERT(value_representation.IsSmiOrTagged() || | 2258 DCHECK(value_representation.IsSmiOrTagged() || |
| 2259 value_representation.IsInteger32()); | 2259 value_representation.IsInteger32()); |
| 2260 if (needs_write_barrier) { | 2260 if (needs_write_barrier) { |
| 2261 object = UseTempRegister(instr->elements()); | 2261 object = UseTempRegister(instr->elements()); |
| 2262 val = UseTempRegister(instr->value()); | 2262 val = UseTempRegister(instr->value()); |
| 2263 key = UseTempRegister(instr->key()); | 2263 key = UseTempRegister(instr->key()); |
| 2264 } else { | 2264 } else { |
| 2265 object = UseRegisterAtStart(instr->elements()); | 2265 object = UseRegisterAtStart(instr->elements()); |
| 2266 val = UseRegisterOrConstantAtStart(instr->value()); | 2266 val = UseRegisterOrConstantAtStart(instr->value()); |
| 2267 key = UseRegisterOrConstantAtStart(instr->key()); | 2267 key = UseRegisterOrConstantAtStart(instr->key()); |
| 2268 } | 2268 } |
| 2269 } | 2269 } |
| 2270 | 2270 |
| 2271 return new(zone()) LStoreKeyed(object, key, val); | 2271 return new(zone()) LStoreKeyed(object, key, val); |
| 2272 } | 2272 } |
| 2273 | 2273 |
| 2274 ASSERT( | 2274 DCHECK( |
| 2275 (instr->value()->representation().IsInteger32() && | 2275 (instr->value()->representation().IsInteger32() && |
| 2276 !IsDoubleOrFloatElementsKind(elements_kind)) || | 2276 !IsDoubleOrFloatElementsKind(elements_kind)) || |
| 2277 (instr->value()->representation().IsDouble() && | 2277 (instr->value()->representation().IsDouble() && |
| 2278 IsDoubleOrFloatElementsKind(elements_kind))); | 2278 IsDoubleOrFloatElementsKind(elements_kind))); |
| 2279 ASSERT((instr->is_fixed_typed_array() && | 2279 DCHECK((instr->is_fixed_typed_array() && |
| 2280 instr->elements()->representation().IsTagged()) || | 2280 instr->elements()->representation().IsTagged()) || |
| 2281 (instr->is_external() && | 2281 (instr->is_external() && |
| 2282 instr->elements()->representation().IsExternal())); | 2282 instr->elements()->representation().IsExternal())); |
| 2283 bool val_is_temp_register = | 2283 bool val_is_temp_register = |
| 2284 elements_kind == EXTERNAL_UINT8_CLAMPED_ELEMENTS || | 2284 elements_kind == EXTERNAL_UINT8_CLAMPED_ELEMENTS || |
| 2285 elements_kind == EXTERNAL_FLOAT32_ELEMENTS || | 2285 elements_kind == EXTERNAL_FLOAT32_ELEMENTS || |
| 2286 elements_kind == FLOAT32_ELEMENTS; | 2286 elements_kind == FLOAT32_ELEMENTS; |
| 2287 LOperand* val = val_is_temp_register ? UseTempRegister(instr->value()) | 2287 LOperand* val = val_is_temp_register ? UseTempRegister(instr->value()) |
| 2288 : UseRegister(instr->value()); | 2288 : UseRegister(instr->value()); |
| 2289 LOperand* key = NULL; | 2289 LOperand* key = NULL; |
| (...skipping 11 matching lines...) Expand all Loading... |
| 2301 } | 2301 } |
| 2302 | 2302 |
| 2303 | 2303 |
| 2304 LInstruction* LChunkBuilder::DoStoreKeyedGeneric(HStoreKeyedGeneric* instr) { | 2304 LInstruction* LChunkBuilder::DoStoreKeyedGeneric(HStoreKeyedGeneric* instr) { |
| 2305 LOperand* context = UseFixed(instr->context(), rsi); | 2305 LOperand* context = UseFixed(instr->context(), rsi); |
| 2306 LOperand* object = UseFixed(instr->object(), | 2306 LOperand* object = UseFixed(instr->object(), |
| 2307 KeyedStoreIC::ReceiverRegister()); | 2307 KeyedStoreIC::ReceiverRegister()); |
| 2308 LOperand* key = UseFixed(instr->key(), KeyedStoreIC::NameRegister()); | 2308 LOperand* key = UseFixed(instr->key(), KeyedStoreIC::NameRegister()); |
| 2309 LOperand* value = UseFixed(instr->value(), KeyedStoreIC::ValueRegister()); | 2309 LOperand* value = UseFixed(instr->value(), KeyedStoreIC::ValueRegister()); |
| 2310 | 2310 |
| 2311 ASSERT(instr->object()->representation().IsTagged()); | 2311 DCHECK(instr->object()->representation().IsTagged()); |
| 2312 ASSERT(instr->key()->representation().IsTagged()); | 2312 DCHECK(instr->key()->representation().IsTagged()); |
| 2313 ASSERT(instr->value()->representation().IsTagged()); | 2313 DCHECK(instr->value()->representation().IsTagged()); |
| 2314 | 2314 |
| 2315 LStoreKeyedGeneric* result = | 2315 LStoreKeyedGeneric* result = |
| 2316 new(zone()) LStoreKeyedGeneric(context, object, key, value); | 2316 new(zone()) LStoreKeyedGeneric(context, object, key, value); |
| 2317 return MarkAsCall(result, instr); | 2317 return MarkAsCall(result, instr); |
| 2318 } | 2318 } |
| 2319 | 2319 |
| 2320 | 2320 |
| 2321 LInstruction* LChunkBuilder::DoTransitionElementsKind( | 2321 LInstruction* LChunkBuilder::DoTransitionElementsKind( |
| 2322 HTransitionElementsKind* instr) { | 2322 HTransitionElementsKind* instr) { |
| 2323 if (IsSimpleMapChangeTransition(instr->from_kind(), instr->to_kind())) { | 2323 if (IsSimpleMapChangeTransition(instr->from_kind(), instr->to_kind())) { |
| (...skipping 30 matching lines...) Expand all Loading... |
| 2354 bool needs_write_barrier = instr->NeedsWriteBarrier(); | 2354 bool needs_write_barrier = instr->NeedsWriteBarrier(); |
| 2355 bool needs_write_barrier_for_map = instr->has_transition() && | 2355 bool needs_write_barrier_for_map = instr->has_transition() && |
| 2356 instr->NeedsWriteBarrierForMap(); | 2356 instr->NeedsWriteBarrierForMap(); |
| 2357 | 2357 |
| 2358 LOperand* obj; | 2358 LOperand* obj; |
| 2359 if (needs_write_barrier) { | 2359 if (needs_write_barrier) { |
| 2360 obj = is_in_object | 2360 obj = is_in_object |
| 2361 ? UseRegister(instr->object()) | 2361 ? UseRegister(instr->object()) |
| 2362 : UseTempRegister(instr->object()); | 2362 : UseTempRegister(instr->object()); |
| 2363 } else if (is_external_location) { | 2363 } else if (is_external_location) { |
| 2364 ASSERT(!is_in_object); | 2364 DCHECK(!is_in_object); |
| 2365 ASSERT(!needs_write_barrier); | 2365 DCHECK(!needs_write_barrier); |
| 2366 ASSERT(!needs_write_barrier_for_map); | 2366 DCHECK(!needs_write_barrier_for_map); |
| 2367 obj = UseRegisterOrConstant(instr->object()); | 2367 obj = UseRegisterOrConstant(instr->object()); |
| 2368 } else { | 2368 } else { |
| 2369 obj = needs_write_barrier_for_map | 2369 obj = needs_write_barrier_for_map |
| 2370 ? UseRegister(instr->object()) | 2370 ? UseRegister(instr->object()) |
| 2371 : UseRegisterAtStart(instr->object()); | 2371 : UseRegisterAtStart(instr->object()); |
| 2372 } | 2372 } |
| 2373 | 2373 |
| 2374 bool can_be_constant = instr->value()->IsConstant() && | 2374 bool can_be_constant = instr->value()->IsConstant() && |
| 2375 HConstant::cast(instr->value())->NotInNewSpace() && | 2375 HConstant::cast(instr->value())->NotInNewSpace() && |
| 2376 !instr->field_representation().IsDouble(); | 2376 !instr->field_representation().IsDouble(); |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2458 | 2458 |
| 2459 | 2459 |
| 2460 LInstruction* LChunkBuilder::DoFunctionLiteral(HFunctionLiteral* instr) { | 2460 LInstruction* LChunkBuilder::DoFunctionLiteral(HFunctionLiteral* instr) { |
| 2461 LOperand* context = UseFixed(instr->context(), rsi); | 2461 LOperand* context = UseFixed(instr->context(), rsi); |
| 2462 LFunctionLiteral* result = new(zone()) LFunctionLiteral(context); | 2462 LFunctionLiteral* result = new(zone()) LFunctionLiteral(context); |
| 2463 return MarkAsCall(DefineFixed(result, rax), instr); | 2463 return MarkAsCall(DefineFixed(result, rax), instr); |
| 2464 } | 2464 } |
| 2465 | 2465 |
| 2466 | 2466 |
| 2467 LInstruction* LChunkBuilder::DoOsrEntry(HOsrEntry* instr) { | 2467 LInstruction* LChunkBuilder::DoOsrEntry(HOsrEntry* instr) { |
| 2468 ASSERT(argument_count_ == 0); | 2468 DCHECK(argument_count_ == 0); |
| 2469 allocator_->MarkAsOsrEntry(); | 2469 allocator_->MarkAsOsrEntry(); |
| 2470 current_block_->last_environment()->set_ast_id(instr->ast_id()); | 2470 current_block_->last_environment()->set_ast_id(instr->ast_id()); |
| 2471 return AssignEnvironment(new(zone()) LOsrEntry); | 2471 return AssignEnvironment(new(zone()) LOsrEntry); |
| 2472 } | 2472 } |
| 2473 | 2473 |
| 2474 | 2474 |
| 2475 LInstruction* LChunkBuilder::DoParameter(HParameter* instr) { | 2475 LInstruction* LChunkBuilder::DoParameter(HParameter* instr) { |
| 2476 LParameter* result = new(zone()) LParameter; | 2476 LParameter* result = new(zone()) LParameter; |
| 2477 if (instr->kind() == HParameter::STACK_PARAMETER) { | 2477 if (instr->kind() == HParameter::STACK_PARAMETER) { |
| 2478 int spill_index = chunk()->GetParameterStackSlot(instr->index()); | 2478 int spill_index = chunk()->GetParameterStackSlot(instr->index()); |
| 2479 return DefineAsSpilled(result, spill_index); | 2479 return DefineAsSpilled(result, spill_index); |
| 2480 } else { | 2480 } else { |
| 2481 ASSERT(info()->IsStub()); | 2481 DCHECK(info()->IsStub()); |
| 2482 CodeStubInterfaceDescriptor* descriptor = | 2482 CodeStubInterfaceDescriptor* descriptor = |
| 2483 info()->code_stub()->GetInterfaceDescriptor(); | 2483 info()->code_stub()->GetInterfaceDescriptor(); |
| 2484 int index = static_cast<int>(instr->index()); | 2484 int index = static_cast<int>(instr->index()); |
| 2485 Register reg = descriptor->GetEnvironmentParameterRegister(index); | 2485 Register reg = descriptor->GetEnvironmentParameterRegister(index); |
| 2486 return DefineFixed(result, reg); | 2486 return DefineFixed(result, reg); |
| 2487 } | 2487 } |
| 2488 } | 2488 } |
| 2489 | 2489 |
| 2490 | 2490 |
| 2491 LInstruction* LChunkBuilder::DoUnknownOSRValue(HUnknownOSRValue* instr) { | 2491 LInstruction* LChunkBuilder::DoUnknownOSRValue(HUnknownOSRValue* instr) { |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2577 return NULL; | 2577 return NULL; |
| 2578 } | 2578 } |
| 2579 | 2579 |
| 2580 | 2580 |
| 2581 LInstruction* LChunkBuilder::DoStackCheck(HStackCheck* instr) { | 2581 LInstruction* LChunkBuilder::DoStackCheck(HStackCheck* instr) { |
| 2582 info()->MarkAsDeferredCalling(); | 2582 info()->MarkAsDeferredCalling(); |
| 2583 if (instr->is_function_entry()) { | 2583 if (instr->is_function_entry()) { |
| 2584 LOperand* context = UseFixed(instr->context(), rsi); | 2584 LOperand* context = UseFixed(instr->context(), rsi); |
| 2585 return MarkAsCall(new(zone()) LStackCheck(context), instr); | 2585 return MarkAsCall(new(zone()) LStackCheck(context), instr); |
| 2586 } else { | 2586 } else { |
| 2587 ASSERT(instr->is_backwards_branch()); | 2587 DCHECK(instr->is_backwards_branch()); |
| 2588 LOperand* context = UseAny(instr->context()); | 2588 LOperand* context = UseAny(instr->context()); |
| 2589 return AssignEnvironment( | 2589 return AssignEnvironment( |
| 2590 AssignPointerMap(new(zone()) LStackCheck(context))); | 2590 AssignPointerMap(new(zone()) LStackCheck(context))); |
| 2591 } | 2591 } |
| 2592 } | 2592 } |
| 2593 | 2593 |
| 2594 | 2594 |
| 2595 LInstruction* LChunkBuilder::DoEnterInlined(HEnterInlined* instr) { | 2595 LInstruction* LChunkBuilder::DoEnterInlined(HEnterInlined* instr) { |
| 2596 HEnvironment* outer = current_block_->last_environment(); | 2596 HEnvironment* outer = current_block_->last_environment(); |
| 2597 outer->set_ast_id(instr->ReturnId()); | 2597 outer->set_ast_id(instr->ReturnId()); |
| (...skipping 15 matching lines...) Expand all Loading... |
| 2613 | 2613 |
| 2614 | 2614 |
| 2615 LInstruction* LChunkBuilder::DoLeaveInlined(HLeaveInlined* instr) { | 2615 LInstruction* LChunkBuilder::DoLeaveInlined(HLeaveInlined* instr) { |
| 2616 LInstruction* pop = NULL; | 2616 LInstruction* pop = NULL; |
| 2617 | 2617 |
| 2618 HEnvironment* env = current_block_->last_environment(); | 2618 HEnvironment* env = current_block_->last_environment(); |
| 2619 | 2619 |
| 2620 if (env->entry()->arguments_pushed()) { | 2620 if (env->entry()->arguments_pushed()) { |
| 2621 int argument_count = env->arguments_environment()->parameter_count(); | 2621 int argument_count = env->arguments_environment()->parameter_count(); |
| 2622 pop = new(zone()) LDrop(argument_count); | 2622 pop = new(zone()) LDrop(argument_count); |
| 2623 ASSERT(instr->argument_delta() == -argument_count); | 2623 DCHECK(instr->argument_delta() == -argument_count); |
| 2624 } | 2624 } |
| 2625 | 2625 |
| 2626 HEnvironment* outer = current_block_->last_environment()-> | 2626 HEnvironment* outer = current_block_->last_environment()-> |
| 2627 DiscardInlined(false); | 2627 DiscardInlined(false); |
| 2628 current_block_->UpdateEnvironment(outer); | 2628 current_block_->UpdateEnvironment(outer); |
| 2629 | 2629 |
| 2630 return pop; | 2630 return pop; |
| 2631 } | 2631 } |
| 2632 | 2632 |
| 2633 | 2633 |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2674 LOperand* function = UseRegisterAtStart(instr->function()); | 2674 LOperand* function = UseRegisterAtStart(instr->function()); |
| 2675 LAllocateBlockContext* result = | 2675 LAllocateBlockContext* result = |
| 2676 new(zone()) LAllocateBlockContext(context, function); | 2676 new(zone()) LAllocateBlockContext(context, function); |
| 2677 return MarkAsCall(DefineFixed(result, rsi), instr); | 2677 return MarkAsCall(DefineFixed(result, rsi), instr); |
| 2678 } | 2678 } |
| 2679 | 2679 |
| 2680 | 2680 |
| 2681 } } // namespace v8::internal | 2681 } } // namespace v8::internal |
| 2682 | 2682 |
| 2683 #endif // V8_TARGET_ARCH_X64 | 2683 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |