OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved.7 | 1 // Copyright 2012 the V8 project authors. All rights reserved.7 |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 2039 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2050 __ BranchF(chunk_->GetAssemblyLabel(left_block), NULL, | 2050 __ BranchF(chunk_->GetAssemblyLabel(left_block), NULL, |
2051 condition, src1, src2); | 2051 condition, src1, src2); |
2052 } else { | 2052 } else { |
2053 __ BranchF(chunk_->GetAssemblyLabel(left_block), NULL, | 2053 __ BranchF(chunk_->GetAssemblyLabel(left_block), NULL, |
2054 condition, src1, src2); | 2054 condition, src1, src2); |
2055 __ Branch(chunk_->GetAssemblyLabel(right_block)); | 2055 __ Branch(chunk_->GetAssemblyLabel(right_block)); |
2056 } | 2056 } |
2057 } | 2057 } |
2058 | 2058 |
2059 | 2059 |
2060 template<class InstrType> | 2060 template <class InstrType> |
2061 void LCodeGen::EmitFalseBranch(InstrType instr, | 2061 void LCodeGen::EmitTrueBranch(InstrType instr, Condition condition, |
2062 Condition condition, | 2062 Register src1, const Operand& src2) { |
2063 Register src1, | 2063 int true_block = instr->TrueDestination(chunk_); |
2064 const Operand& src2) { | 2064 __ Branch(chunk_->GetAssemblyLabel(true_block), condition, src1, src2); |
| 2065 } |
| 2066 |
| 2067 |
| 2068 template <class InstrType> |
| 2069 void LCodeGen::EmitFalseBranch(InstrType instr, Condition condition, |
| 2070 Register src1, const Operand& src2) { |
2065 int false_block = instr->FalseDestination(chunk_); | 2071 int false_block = instr->FalseDestination(chunk_); |
2066 __ Branch(chunk_->GetAssemblyLabel(false_block), condition, src1, src2); | 2072 __ Branch(chunk_->GetAssemblyLabel(false_block), condition, src1, src2); |
2067 } | 2073 } |
2068 | 2074 |
2069 | 2075 |
2070 template<class InstrType> | 2076 template<class InstrType> |
2071 void LCodeGen::EmitFalseBranchF(InstrType instr, | 2077 void LCodeGen::EmitFalseBranchF(InstrType instr, |
2072 Condition condition, | 2078 Condition condition, |
2073 FPURegister src1, | 2079 FPURegister src1, |
2074 FPURegister src2) { | 2080 FPURegister src2) { |
(...skipping 569 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2644 Register reg = ToRegister(instr->value()); | 2650 Register reg = ToRegister(instr->value()); |
2645 Register temp = ToRegister(instr->temp()); | 2651 Register temp = ToRegister(instr->temp()); |
2646 | 2652 |
2647 __ lw(temp, FieldMemOperand(reg, HeapObject::kMapOffset)); | 2653 __ lw(temp, FieldMemOperand(reg, HeapObject::kMapOffset)); |
2648 EmitBranch(instr, eq, temp, Operand(instr->map())); | 2654 EmitBranch(instr, eq, temp, Operand(instr->map())); |
2649 } | 2655 } |
2650 | 2656 |
2651 | 2657 |
2652 void LCodeGen::DoInstanceOf(LInstanceOf* instr) { | 2658 void LCodeGen::DoInstanceOf(LInstanceOf* instr) { |
2653 DCHECK(ToRegister(instr->context()).is(cp)); | 2659 DCHECK(ToRegister(instr->context()).is(cp)); |
2654 Label true_label, done; | 2660 DCHECK(ToRegister(instr->left()).is(InstanceOfDescriptor::LeftRegister())); |
2655 DCHECK(ToRegister(instr->left()).is(a0)); // Object is in a0. | 2661 DCHECK(ToRegister(instr->right()).is(InstanceOfDescriptor::RightRegister())); |
2656 DCHECK(ToRegister(instr->right()).is(a1)); // Function is in a1. | 2662 DCHECK(ToRegister(instr->result()).is(v0)); |
2657 Register result = ToRegister(instr->result()); | 2663 InstanceOfStub stub(isolate()); |
2658 DCHECK(result.is(v0)); | |
2659 | |
2660 InstanceofStub stub(isolate(), InstanceofStub::kArgsInRegisters); | |
2661 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); | 2664 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
2662 | |
2663 __ Branch(&true_label, eq, result, Operand(zero_reg)); | |
2664 __ li(result, Operand(factory()->false_value())); | |
2665 __ Branch(&done); | |
2666 __ bind(&true_label); | |
2667 __ li(result, Operand(factory()->true_value())); | |
2668 __ bind(&done); | |
2669 } | 2665 } |
2670 | 2666 |
2671 | 2667 |
2672 void LCodeGen::DoInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr) { | 2668 void LCodeGen::DoHasInPrototypeChainAndBranch( |
2673 class DeferredInstanceOfKnownGlobal final : public LDeferredCode { | 2669 LHasInPrototypeChainAndBranch* instr) { |
2674 public: | 2670 Register const object = ToRegister(instr->object()); |
2675 DeferredInstanceOfKnownGlobal(LCodeGen* codegen, | 2671 Register const object_map = scratch0(); |
2676 LInstanceOfKnownGlobal* instr) | 2672 Register const object_prototype = object_map; |
2677 : LDeferredCode(codegen), instr_(instr) { } | 2673 Register const prototype = ToRegister(instr->prototype()); |
2678 void Generate() override { | |
2679 codegen()->DoDeferredInstanceOfKnownGlobal(instr_, &map_check_); | |
2680 } | |
2681 LInstruction* instr() override { return instr_; } | |
2682 Label* map_check() { return &map_check_; } | |
2683 | 2674 |
2684 private: | 2675 // The {object} must be a spec object. It's sufficient to know that {object} |
2685 LInstanceOfKnownGlobal* instr_; | 2676 // is not a smi, since all other non-spec objects have {null} prototypes and |
2686 Label map_check_; | 2677 // will be ruled out below. |
2687 }; | 2678 if (instr->hydrogen()->ObjectNeedsSmiCheck()) { |
2688 | 2679 __ SmiTst(object, at); |
2689 DeferredInstanceOfKnownGlobal* deferred; | 2680 EmitFalseBranch(instr, eq, at, Operand(zero_reg)); |
2690 deferred = new(zone()) DeferredInstanceOfKnownGlobal(this, instr); | 2681 } |
2691 | 2682 // Loop through the {object}s prototype chain looking for the {prototype}. |
2692 Label done, false_result; | 2683 __ lw(object_map, FieldMemOperand(object, HeapObject::kMapOffset)); |
2693 Register object = ToRegister(instr->value()); | 2684 Label loop; |
2694 Register temp = ToRegister(instr->temp()); | 2685 __ bind(&loop); |
2695 Register result = ToRegister(instr->result()); | 2686 __ lw(object_prototype, FieldMemOperand(object_map, Map::kPrototypeOffset)); |
2696 | 2687 EmitTrueBranch(instr, eq, object_prototype, Operand(prototype)); |
2697 DCHECK(object.is(a0)); | 2688 __ LoadRoot(at, Heap::kNullValueRootIndex); |
2698 DCHECK(result.is(v0)); | 2689 EmitFalseBranch(instr, eq, object_prototype, Operand(at)); |
2699 | 2690 __ Branch(USE_DELAY_SLOT, &loop); |
2700 // A Smi is not instance of anything. | 2691 __ lw(object_map, FieldMemOperand(object_prototype, HeapObject::kMapOffset)); |
2701 __ JumpIfSmi(object, &false_result); | |
2702 | |
2703 // This is the inlined call site instanceof cache. The two occurences of the | |
2704 // hole value will be patched to the last map/result pair generated by the | |
2705 // instanceof stub. | |
2706 Label cache_miss; | |
2707 Register map = temp; | |
2708 __ lw(map, FieldMemOperand(object, HeapObject::kMapOffset)); | |
2709 | |
2710 Assembler::BlockTrampolinePoolScope block_trampoline_pool(masm_); | |
2711 __ bind(deferred->map_check()); // Label for calculating code patching. | |
2712 // We use Factory::the_hole_value() on purpose instead of loading from the | |
2713 // root array to force relocation to be able to later patch with | |
2714 // the cached map. | |
2715 Handle<Cell> cell = factory()->NewCell(factory()->the_hole_value()); | |
2716 __ li(at, Operand(cell)); | |
2717 __ lw(at, FieldMemOperand(at, Cell::kValueOffset)); | |
2718 __ BranchShort(&cache_miss, ne, map, Operand(at)); | |
2719 // We use Factory::the_hole_value() on purpose instead of loading from the | |
2720 // root array to force relocation to be able to later patch | |
2721 // with true or false. The distance from map check has to be constant. | |
2722 __ li(result, Operand(factory()->the_hole_value()), CONSTANT_SIZE); | |
2723 __ Branch(&done); | |
2724 | |
2725 // The inlined call site cache did not match. Check null and string before | |
2726 // calling the deferred code. | |
2727 __ bind(&cache_miss); | |
2728 // Null is not instance of anything. | |
2729 __ LoadRoot(temp, Heap::kNullValueRootIndex); | |
2730 __ Branch(&false_result, eq, object, Operand(temp)); | |
2731 | |
2732 // String values is not instance of anything. | |
2733 Condition cc = __ IsObjectStringType(object, temp, temp); | |
2734 __ Branch(&false_result, cc, temp, Operand(zero_reg)); | |
2735 | |
2736 // Go to the deferred code. | |
2737 __ Branch(deferred->entry()); | |
2738 | |
2739 __ bind(&false_result); | |
2740 __ LoadRoot(result, Heap::kFalseValueRootIndex); | |
2741 | |
2742 // Here result has either true or false. Deferred code also produces true or | |
2743 // false object. | |
2744 __ bind(deferred->exit()); | |
2745 __ bind(&done); | |
2746 } | 2692 } |
2747 | 2693 |
2748 | 2694 |
2749 void LCodeGen::DoDeferredInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr, | |
2750 Label* map_check) { | |
2751 Register result = ToRegister(instr->result()); | |
2752 DCHECK(result.is(v0)); | |
2753 | |
2754 InstanceofStub::Flags flags = InstanceofStub::kNoFlags; | |
2755 flags = static_cast<InstanceofStub::Flags>( | |
2756 flags | InstanceofStub::kArgsInRegisters); | |
2757 flags = static_cast<InstanceofStub::Flags>( | |
2758 flags | InstanceofStub::kCallSiteInlineCheck); | |
2759 flags = static_cast<InstanceofStub::Flags>( | |
2760 flags | InstanceofStub::kReturnTrueFalseObject); | |
2761 InstanceofStub stub(isolate(), flags); | |
2762 | |
2763 PushSafepointRegistersScope scope(this); | |
2764 LoadContextFromDeferred(instr->context()); | |
2765 | |
2766 // Get the temp register reserved by the instruction. This needs to be t0 as | |
2767 // its slot of the pushing of safepoint registers is used to communicate the | |
2768 // offset to the location of the map check. | |
2769 Register temp = ToRegister(instr->temp()); | |
2770 DCHECK(temp.is(t0)); | |
2771 __ li(InstanceofStub::right(), instr->function()); | |
2772 static const int kAdditionalDelta = 7; | |
2773 int delta = masm_->InstructionsGeneratedSince(map_check) + kAdditionalDelta; | |
2774 Label before_push_delta; | |
2775 __ bind(&before_push_delta); | |
2776 { | |
2777 Assembler::BlockTrampolinePoolScope block_trampoline_pool(masm_); | |
2778 __ li(temp, Operand(delta * kPointerSize), CONSTANT_SIZE); | |
2779 __ StoreToSafepointRegisterSlot(temp, temp); | |
2780 } | |
2781 CallCodeGeneric(stub.GetCode(), | |
2782 RelocInfo::CODE_TARGET, | |
2783 instr, | |
2784 RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS); | |
2785 LEnvironment* env = instr->GetDeferredLazyDeoptimizationEnvironment(); | |
2786 safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index()); | |
2787 // Put the result value into the result register slot and | |
2788 // restore all registers. | |
2789 __ StoreToSafepointRegisterSlot(result, result); | |
2790 } | |
2791 | |
2792 | |
2793 void LCodeGen::DoCmpT(LCmpT* instr) { | 2695 void LCodeGen::DoCmpT(LCmpT* instr) { |
2794 DCHECK(ToRegister(instr->context()).is(cp)); | 2696 DCHECK(ToRegister(instr->context()).is(cp)); |
2795 Token::Value op = instr->op(); | 2697 Token::Value op = instr->op(); |
2796 | 2698 |
2797 Handle<Code> ic = | 2699 Handle<Code> ic = |
2798 CodeFactory::CompareIC(isolate(), op, instr->strength()).code(); | 2700 CodeFactory::CompareIC(isolate(), op, instr->strength()).code(); |
2799 CallCode(ic, RelocInfo::CODE_TARGET, instr); | 2701 CallCode(ic, RelocInfo::CODE_TARGET, instr); |
2800 // On MIPS there is no need for a "no inlined smi code" marker (nop). | 2702 // On MIPS there is no need for a "no inlined smi code" marker (nop). |
2801 | 2703 |
2802 Condition condition = ComputeCompareCondition(op); | 2704 Condition condition = ComputeCompareCondition(op); |
(...skipping 3262 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6065 __ Push(at, ToRegister(instr->function())); | 5967 __ Push(at, ToRegister(instr->function())); |
6066 CallRuntime(Runtime::kPushBlockContext, 2, instr); | 5968 CallRuntime(Runtime::kPushBlockContext, 2, instr); |
6067 RecordSafepoint(Safepoint::kNoLazyDeopt); | 5969 RecordSafepoint(Safepoint::kNoLazyDeopt); |
6068 } | 5970 } |
6069 | 5971 |
6070 | 5972 |
6071 #undef __ | 5973 #undef __ |
6072 | 5974 |
6073 } // namespace internal | 5975 } // namespace internal |
6074 } // namespace v8 | 5976 } // namespace v8 |
OLD | NEW |