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

Side by Side Diff: src/mips/lithium-codegen-mips.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/mips/lithium-codegen-mips.h ('k') | src/mips/lithium-mips.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.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
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
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
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
OLDNEW
« no previous file with comments | « src/mips/lithium-codegen-mips.h ('k') | src/mips/lithium-mips.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698