Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(4)

Side by Side Diff: src/mips64/lithium-codegen-mips64.cc

Issue 1304633002: Correctify instanceof and make it optimizable. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: REBASE. Add MIPS/MIPS64 ports. Created 5 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/mips64/lithium-codegen-mips64.h ('k') | src/mips64/lithium-mips64.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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/code-factory.h" 5 #include "src/code-factory.h"
6 #include "src/code-stubs.h" 6 #include "src/code-stubs.h"
7 #include "src/cpu-profiler.h" 7 #include "src/cpu-profiler.h"
8 #include "src/hydrogen-osr.h" 8 #include "src/hydrogen-osr.h"
9 #include "src/ic/ic.h" 9 #include "src/ic/ic.h"
10 #include "src/ic/stub-cache.h" 10 #include "src/ic/stub-cache.h"
(...skipping 2140 matching lines...) Expand 10 before | Expand all | Expand 10 after
2151 __ BranchF(chunk_->GetAssemblyLabel(left_block), NULL, 2151 __ BranchF(chunk_->GetAssemblyLabel(left_block), NULL,
2152 condition, src1, src2); 2152 condition, src1, src2);
2153 } else { 2153 } else {
2154 __ BranchF(chunk_->GetAssemblyLabel(left_block), NULL, 2154 __ BranchF(chunk_->GetAssemblyLabel(left_block), NULL,
2155 condition, src1, src2); 2155 condition, src1, src2);
2156 __ Branch(chunk_->GetAssemblyLabel(right_block)); 2156 __ Branch(chunk_->GetAssemblyLabel(right_block));
2157 } 2157 }
2158 } 2158 }
2159 2159
2160 2160
2161 template<class InstrType> 2161 template <class InstrType>
2162 void LCodeGen::EmitFalseBranch(InstrType instr, 2162 void LCodeGen::EmitTrueBranch(InstrType instr, Condition condition,
2163 Condition condition, 2163 Register src1, const Operand& src2) {
2164 Register src1, 2164 int true_block = instr->TrueDestination(chunk_);
2165 const Operand& src2) { 2165 __ Branch(chunk_->GetAssemblyLabel(true_block), condition, src1, src2);
2166 }
2167
2168
2169 template <class InstrType>
2170 void LCodeGen::EmitFalseBranch(InstrType instr, Condition condition,
2171 Register src1, const Operand& src2) {
2166 int false_block = instr->FalseDestination(chunk_); 2172 int false_block = instr->FalseDestination(chunk_);
2167 __ Branch(chunk_->GetAssemblyLabel(false_block), condition, src1, src2); 2173 __ Branch(chunk_->GetAssemblyLabel(false_block), condition, src1, src2);
2168 } 2174 }
2169 2175
2170 2176
2171 template<class InstrType> 2177 template<class InstrType>
2172 void LCodeGen::EmitFalseBranchF(InstrType instr, 2178 void LCodeGen::EmitFalseBranchF(InstrType instr,
2173 Condition condition, 2179 Condition condition,
2174 FPURegister src1, 2180 FPURegister src1,
2175 FPURegister src2) { 2181 FPURegister src2) {
(...skipping 573 matching lines...) Expand 10 before | Expand all | Expand 10 after
2749 Register temp = ToRegister(instr->temp()); 2755 Register temp = ToRegister(instr->temp());
2750 2756
2751 __ ld(temp, FieldMemOperand(reg, HeapObject::kMapOffset)); 2757 __ ld(temp, FieldMemOperand(reg, HeapObject::kMapOffset));
2752 EmitBranch(instr, eq, temp, Operand(instr->map())); 2758 EmitBranch(instr, eq, temp, Operand(instr->map()));
2753 } 2759 }
2754 2760
2755 2761
2756 void LCodeGen::DoInstanceOf(LInstanceOf* instr) { 2762 void LCodeGen::DoInstanceOf(LInstanceOf* instr) {
2757 DCHECK(ToRegister(instr->context()).is(cp)); 2763 DCHECK(ToRegister(instr->context()).is(cp));
2758 Label true_label, done; 2764 Label true_label, done;
2759 DCHECK(ToRegister(instr->left()).is(a0)); // Object is in a0. 2765 DCHECK(ToRegister(instr->left()).is(InstanceOfDescriptor::LeftRegister()));
2760 DCHECK(ToRegister(instr->right()).is(a1)); // Function is in a1. 2766 DCHECK(ToRegister(instr->right()).is(InstanceOfDescriptor::RightRegister()));
2761 Register result = ToRegister(instr->result()); 2767 DCHECK(ToRegister(instr->result()).is(v0));
2762 DCHECK(result.is(v0));
2763 2768
2764 InstanceofStub stub(isolate(), InstanceofStub::kArgsInRegisters); 2769 InstanceOfStub stub(isolate());
2765 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); 2770 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
2766
2767 __ Branch(&true_label, eq, result, Operand(zero_reg));
2768 __ li(result, Operand(factory()->false_value()));
2769 __ Branch(&done);
2770 __ bind(&true_label);
2771 __ li(result, Operand(factory()->true_value()));
2772 __ bind(&done);
2773 } 2771 }
2774 2772
2775 2773
2776 void LCodeGen::DoInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr) { 2774 void LCodeGen::DoHasInPrototypeChainAndBranch(
2777 class DeferredInstanceOfKnownGlobal final : public LDeferredCode { 2775 LHasInPrototypeChainAndBranch* instr) {
2778 public: 2776 Register const object = ToRegister(instr->object());
2779 DeferredInstanceOfKnownGlobal(LCodeGen* codegen, 2777 Register const object_map = scratch0();
2780 LInstanceOfKnownGlobal* instr) 2778 Register const object_prototype = object_map;
2781 : LDeferredCode(codegen), instr_(instr) { } 2779 Register const prototype = ToRegister(instr->prototype());
2782 void Generate() override {
2783 codegen()->DoDeferredInstanceOfKnownGlobal(instr_, &map_check_);
2784 }
2785 LInstruction* instr() override { return instr_; }
2786 Label* map_check() { return &map_check_; }
2787 2780
2788 private: 2781 // The {object} must be a spec object. It's sufficient to know that {object}
2789 LInstanceOfKnownGlobal* instr_; 2782 // is not a smi, since all other non-spec objects have {null} prototypes and
2790 Label map_check_; 2783 // will be ruled out below.
2791 }; 2784 if (instr->hydrogen()->ObjectNeedsSmiCheck()) {
2785 __ SmiTst(object, at);
2786 EmitFalseBranch(instr, eq, at, Operand(zero_reg));
2787 }
2792 2788
2793 DeferredInstanceOfKnownGlobal* deferred; 2789 // Loop through the {object}s prototype chain looking for the {prototype}.
2794 deferred = new(zone()) DeferredInstanceOfKnownGlobal(this, instr); 2790 __ ld(object_map, FieldMemOperand(object, HeapObject::kMapOffset));
2795 2791 Label loop;
2796 Label done, false_result; 2792 __ bind(&loop);
2797 Register object = ToRegister(instr->value()); 2793 __ ld(object_prototype, FieldMemOperand(object_map, Map::kPrototypeOffset));
2798 Register temp = ToRegister(instr->temp()); 2794 EmitTrueBranch(instr, eq, object_prototype, Operand(prototype));
2799 Register result = ToRegister(instr->result()); 2795 __ LoadRoot(at, Heap::kNullValueRootIndex);
2800 2796 EmitFalseBranch(instr, eq, object_prototype, Operand(at));
2801 DCHECK(object.is(a0)); 2797 __ Branch(&loop, USE_DELAY_SLOT);
2802 DCHECK(result.is(v0)); 2798 __ ld(object_map, FieldMemOperand(object_prototype,
2803 2799 HeapObject::kMapOffset)); // In delay slot.
2804 // A Smi is not instance of anything.
2805 __ JumpIfSmi(object, &false_result);
2806
2807 // This is the inlined call site instanceof cache. The two occurences of the
2808 // hole value will be patched to the last map/result pair generated by the
2809 // instanceof stub.
2810 Label cache_miss;
2811 Register map = temp;
2812 __ ld(map, FieldMemOperand(object, HeapObject::kMapOffset));
2813
2814 Assembler::BlockTrampolinePoolScope block_trampoline_pool(masm_);
2815 __ bind(deferred->map_check()); // Label for calculating code patching.
2816 // We use Factory::the_hole_value() on purpose instead of loading from the
2817 // root array to force relocation to be able to later patch with
2818 // the cached map.
2819 Handle<Cell> cell = factory()->NewCell(factory()->the_hole_value());
2820 __ li(at, Operand(cell));
2821 __ ld(at, FieldMemOperand(at, Cell::kValueOffset));
2822 __ BranchShort(&cache_miss, ne, map, Operand(at));
2823 // We use Factory::the_hole_value() on purpose instead of loading from the
2824 // root array to force relocation to be able to later patch
2825 // with true or false. The distance from map check has to be constant.
2826 __ li(result, Operand(factory()->the_hole_value()));
2827 __ Branch(&done);
2828
2829 // The inlined call site cache did not match. Check null and string before
2830 // calling the deferred code.
2831 __ bind(&cache_miss);
2832 // Null is not instance of anything.
2833 __ LoadRoot(temp, Heap::kNullValueRootIndex);
2834 __ Branch(&false_result, eq, object, Operand(temp));
2835
2836 // String values is not instance of anything.
2837 Condition cc = __ IsObjectStringType(object, temp, temp);
2838 __ Branch(&false_result, cc, temp, Operand(zero_reg));
2839
2840 // Go to the deferred code.
2841 __ Branch(deferred->entry());
2842
2843 __ bind(&false_result);
2844 __ LoadRoot(result, Heap::kFalseValueRootIndex);
2845
2846 // Here result has either true or false. Deferred code also produces true or
2847 // false object.
2848 __ bind(deferred->exit());
2849 __ bind(&done);
2850 } 2800 }
2851 2801
2852 2802
2853 void LCodeGen::DoDeferredInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr,
2854 Label* map_check) {
2855 Register result = ToRegister(instr->result());
2856 DCHECK(result.is(v0));
2857
2858 InstanceofStub::Flags flags = InstanceofStub::kNoFlags;
2859 flags = static_cast<InstanceofStub::Flags>(
2860 flags | InstanceofStub::kArgsInRegisters);
2861 flags = static_cast<InstanceofStub::Flags>(
2862 flags | InstanceofStub::kCallSiteInlineCheck);
2863 flags = static_cast<InstanceofStub::Flags>(
2864 flags | InstanceofStub::kReturnTrueFalseObject);
2865 InstanceofStub stub(isolate(), flags);
2866
2867 PushSafepointRegistersScope scope(this);
2868 LoadContextFromDeferred(instr->context());
2869
2870 // Get the temp register reserved by the instruction. This needs to be a4 as
2871 // its slot of the pushing of safepoint registers is used to communicate the
2872 // offset to the location of the map check.
2873 Register temp = ToRegister(instr->temp());
2874 DCHECK(temp.is(a4));
2875 __ li(InstanceofStub::right(), instr->function());
2876 static const int kAdditionalDelta = 13;
2877 int delta = masm_->InstructionsGeneratedSince(map_check) + kAdditionalDelta;
2878 Label before_push_delta;
2879 __ bind(&before_push_delta);
2880 {
2881 Assembler::BlockTrampolinePoolScope block_trampoline_pool(masm_);
2882 __ li(temp, Operand(delta * kIntSize), CONSTANT_SIZE);
2883 __ StoreToSafepointRegisterSlot(temp, temp);
2884 }
2885 CallCodeGeneric(stub.GetCode(),
2886 RelocInfo::CODE_TARGET,
2887 instr,
2888 RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS);
2889 LEnvironment* env = instr->GetDeferredLazyDeoptimizationEnvironment();
2890 safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index());
2891 // Put the result value into the result register slot and
2892 // restore all registers.
2893 __ StoreToSafepointRegisterSlot(result, result);
2894 }
2895
2896
2897 void LCodeGen::DoCmpT(LCmpT* instr) { 2803 void LCodeGen::DoCmpT(LCmpT* instr) {
2898 DCHECK(ToRegister(instr->context()).is(cp)); 2804 DCHECK(ToRegister(instr->context()).is(cp));
2899 Token::Value op = instr->op(); 2805 Token::Value op = instr->op();
2900 2806
2901 Handle<Code> ic = 2807 Handle<Code> ic =
2902 CodeFactory::CompareIC(isolate(), op, instr->strength()).code(); 2808 CodeFactory::CompareIC(isolate(), op, instr->strength()).code();
2903 CallCode(ic, RelocInfo::CODE_TARGET, instr); 2809 CallCode(ic, RelocInfo::CODE_TARGET, instr);
2904 // On MIPS there is no need for a "no inlined smi code" marker (nop). 2810 // On MIPS there is no need for a "no inlined smi code" marker (nop).
2905 2811
2906 Condition condition = ComputeCompareCondition(op); 2812 Condition condition = ComputeCompareCondition(op);
(...skipping 3341 matching lines...) Expand 10 before | Expand all | Expand 10 after
6248 __ Push(at, ToRegister(instr->function())); 6154 __ Push(at, ToRegister(instr->function()));
6249 CallRuntime(Runtime::kPushBlockContext, 2, instr); 6155 CallRuntime(Runtime::kPushBlockContext, 2, instr);
6250 RecordSafepoint(Safepoint::kNoLazyDeopt); 6156 RecordSafepoint(Safepoint::kNoLazyDeopt);
6251 } 6157 }
6252 6158
6253 6159
6254 #undef __ 6160 #undef __
6255 6161
6256 } // namespace internal 6162 } // namespace internal
6257 } // namespace v8 6163 } // namespace v8
OLDNEW
« no previous file with comments | « src/mips64/lithium-codegen-mips64.h ('k') | src/mips64/lithium-mips64.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698