From 8312b895f37c7a5acba34ba1102ac3702d6f19e2 Mon Sep 17 00:00:00 2001 From: "palfia@homejinni.com" Date: Fri, 8 Mar 2013 00:46:45 +0000 Subject: [PATCH] MIPS: Polymorphism support for load IC. Port r13801 (6de52924) BUG= Review URL: https://codereview.chromium.org/12560004 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@13873 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/mips/code-stubs-mips.cc | 6 +++ src/mips/ic-mips.cc | 3 +- src/mips/stub-cache-mips.cc | 117 ++++++++++++++++++++++++++------------------ 3 files changed, 78 insertions(+), 48 deletions(-) diff --git a/src/mips/code-stubs-mips.cc b/src/mips/code-stubs-mips.cc index 6cf64c4..f1ab7f3 100644 --- a/src/mips/code-stubs-mips.cc +++ b/src/mips/code-stubs-mips.cc @@ -4725,6 +4725,12 @@ Register InstanceofStub::left() { return a0; } Register InstanceofStub::right() { return a1; } +void LoadFieldStub::Generate(MacroAssembler* masm) { + StubCompiler::DoGenerateFastPropertyLoad(masm, v0, reg_, inobject_, index_); + __ Ret(); +} + + void ArgumentsAccessStub::GenerateReadElement(MacroAssembler* masm) { // The displacement is the offset of the last parameter (if any) // relative to the frame pointer. diff --git a/src/mips/ic-mips.cc b/src/mips/ic-mips.cc index 11c8034..24b1b0f 100644 --- a/src/mips/ic-mips.cc +++ b/src/mips/ic-mips.cc @@ -653,7 +653,8 @@ void LoadIC::GenerateMegamorphic(MacroAssembler* masm) { // ----------------------------------- // Probe the stub cache. - Code::Flags flags = Code::ComputeFlags(Code::LOAD_IC, MONOMORPHIC); + Code::Flags flags = Code::ComputeFlags( + Code::LOAD_IC, MONOMORPHIC, Code::HANDLER_FRAGMENT); Isolate::Current()->stub_cache()->GenerateProbe( masm, flags, a0, a2, a3, t0, t1, t2); diff --git a/src/mips/stub-cache-mips.cc b/src/mips/stub-cache-mips.cc index 5dd0e5f..051e64e 100644 --- a/src/mips/stub-cache-mips.cc +++ b/src/mips/stub-cache-mips.cc @@ -315,23 +315,24 @@ void StubCompiler::GenerateFastPropertyLoad(MacroAssembler* masm, Register src, Handle holder, PropertyIndex index) { - if (index.is_header_index()) { - int offset = index.header_index() * kPointerSize; - __ lw(dst, FieldMemOperand(src, offset)); - } else { - // Adjust for the number of properties stored in the holder. - int slot = index.field_index() - holder->map()->inobject_properties(); - if (slot < 0) { - // Get the property straight out of the holder. - int offset = holder->map()->instance_size() + (slot * kPointerSize); - __ lw(dst, FieldMemOperand(src, offset)); - } else { - // Calculate the offset into the properties array. - int offset = slot * kPointerSize + FixedArray::kHeaderSize; - __ lw(dst, FieldMemOperand(src, JSObject::kPropertiesOffset)); - __ lw(dst, FieldMemOperand(dst, offset)); - } + DoGenerateFastPropertyLoad( + masm, dst, src, index.is_inobject(holder), index.translate(holder)); +} + + +void StubCompiler::DoGenerateFastPropertyLoad(MacroAssembler* masm, + Register dst, + Register src, + bool inobject, + int index) { + int offset = index * kPointerSize; + if (!inobject) { + // Calculate the offset into the properties array. + offset = offset + FixedArray::kHeaderSize; + __ lw(dst, FieldMemOperand(src, JSObject::kPropertiesOffset)); + src = dst; } + __ lw(dst, FieldMemOperand(src, offset)); } @@ -1067,6 +1068,11 @@ static void StoreIntAsFloat(MacroAssembler* masm, #define __ ACCESS_MASM(masm()) +void StubCompiler::GenerateTailCall(Handle code) { + __ Jump(code, RelocInfo::CODE_TARGET); +} + + Register StubCompiler::CheckPrototypes(Handle object, Register object_reg, Handle holder, @@ -1075,7 +1081,9 @@ Register StubCompiler::CheckPrototypes(Handle object, Register scratch2, Handle name, int save_at_depth, - Label* miss) { + Label* miss, + PrototypeCheckType check) { + Handle first = object; // Make sure there's no overlap between holder and object registers. ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg) @@ -1116,9 +1124,15 @@ Register StubCompiler::CheckPrototypes(Handle object, reg = holder_reg; // From now on the object will be in holder_reg. __ lw(reg, FieldMemOperand(scratch1, Map::kPrototypeOffset)); } else { - Handle current_map(current->map()); - __ CheckMap(reg, scratch1, current_map, miss, DONT_DO_SMI_CHECK, - ALLOW_ELEMENT_TRANSITION_MAPS); + Register map_reg = scratch1; + if (!current.is_identical_to(first) || check == CHECK_ALL_MAPS) { + Handle current_map(current->map()); + // CheckMap implicitly loads the map of |reg| into |map_reg|. + __ CheckMap(reg, map_reg, current_map, miss, DONT_DO_SMI_CHECK, + ALLOW_ELEMENT_TRANSITION_MAPS); + } else { + __ lw(map_reg, FieldMemOperand(reg, HeapObject::kMapOffset)); + } // Check access rights to the global object. This has to happen after // the map check so that we know that the object is actually a global // object. @@ -1130,7 +1144,7 @@ Register StubCompiler::CheckPrototypes(Handle object, if (heap()->InNewSpace(*prototype)) { // The prototype is in new space; we cannot store a reference to it // in the code. Load it from the map. - __ lw(reg, FieldMemOperand(scratch1, Map::kPrototypeOffset)); + __ lw(reg, FieldMemOperand(map_reg, Map::kPrototypeOffset)); } else { // The prototype is in old space; load it directly. __ li(reg, Operand(prototype)); @@ -1148,9 +1162,11 @@ Register StubCompiler::CheckPrototypes(Handle object, // Log the check depth. LOG(masm()->isolate(), IntEvent("check-maps-depth", depth + 1)); - // Check the holder map. - __ CheckMap(reg, scratch1, Handle(current->map()), miss, - DONT_DO_SMI_CHECK, ALLOW_ELEMENT_TRANSITION_MAPS); + if (!holder.is_identical_to(first) || check == CHECK_ALL_MAPS) { + // Check the holder map. + __ CheckMap(reg, scratch1, Handle(holder->map()), miss, + DONT_DO_SMI_CHECK, ALLOW_ELEMENT_TRANSITION_MAPS); + } // Perform security check for access to the global object. ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded()); @@ -1170,9 +1186,11 @@ Register StubCompiler::CheckPrototypes(Handle object, void BaseLoadStubCompiler::HandlerFrontendFooter(Label* success, Label* miss) { - __ Branch(success); - __ bind(miss); - GenerateLoadMiss(masm(), kind()); + if (!miss->is_unused()) { + __ Branch(success); + __ bind(miss); + GenerateLoadMiss(masm(), kind()); + } } @@ -1182,12 +1200,10 @@ Register BaseLoadStubCompiler::CallbackHandlerFrontend( Handle holder, Handle name, Label* success, - FrontendCheckType check, Handle callback) { Label miss; - Register reg = HandlerFrontendHeader( - object, object_reg, holder, name, &miss, check); + Register reg = HandlerFrontendHeader(object, object_reg, holder, name, &miss); if (!holder->HasFastProperties() && !holder->IsJSGlobalObject()) { ASSERT(!reg.is(scratch2())); @@ -1232,8 +1248,7 @@ void BaseLoadStubCompiler::NonexistentHandlerFrontend( Handle global) { Label miss; - Register reg = HandlerFrontendHeader( - object, receiver(), last, name, &miss, PERFORM_INITIAL_CHECKS); + Register reg = HandlerFrontendHeader(object, receiver(), last, name, &miss); // If the last object in the prototype chain is a global object, // check that the global property cell is empty. @@ -2863,7 +2878,7 @@ Handle LoadStubCompiler::CompileLoadNonexistent( __ Ret(); // Return the generated code. - return GetCode(Code::NONEXISTENT, factory()->empty_string()); + return GetCode(Code::HANDLER_FRAGMENT, Code::NONEXISTENT, name); } @@ -2933,8 +2948,10 @@ Handle LoadStubCompiler::CompileLoadGlobal( bool is_dont_delete) { Label success, miss; - HandlerFrontendHeader(object, receiver(), Handle::cast(global), - name, &miss, PERFORM_INITIAL_CHECKS); + __ CheckMap( + receiver(), scratch1(), Handle(object->map()), &miss, DO_SMI_CHECK); + HandlerFrontendHeader( + object, receiver(), Handle::cast(global), name, &miss); // Get the value from the cell. __ li(a3, Operand(cell)); @@ -2955,7 +2972,7 @@ Handle LoadStubCompiler::CompileLoadGlobal( __ Ret(); // Return the generated code. - return GetCode(Code::NORMAL, name); + return GetCode(Code::IC_FRAGMENT, Code::NORMAL, name); } @@ -2983,33 +3000,39 @@ Handle KeyedLoadStubCompiler::CompileLoadElement( __ Jump(ic, RelocInfo::CODE_TARGET); // Return the generated code. - return GetCode(Code::NORMAL, factory()->empty_string()); + return GetCode(Code::IC_FRAGMENT, Code::NORMAL, factory()->empty_string()); } Handle BaseLoadStubCompiler::CompilePolymorphicIC( MapHandleList* receiver_maps, - CodeHandleList* handlers) { - // ----------- S t a t e ------------- - // -- ra : return address - // -- a0 : key - // -- a1 : receiver - // ----------------------------------- + CodeHandleList* handlers, + Handle name, + Code::StubType type, + IcCheckType check) { Label miss; - __ JumpIfSmi(a1, &miss); + + if (check == PROPERTY) { + GenerateNameCheck(name, this->name(), &miss); + } + + __ JumpIfSmi(receiver(), &miss); + Register map_reg = scratch1(); int receiver_count = receiver_maps->length(); - __ lw(a2, FieldMemOperand(a1, HeapObject::kMapOffset)); + __ lw(map_reg, FieldMemOperand(receiver(), HeapObject::kMapOffset)); for (int current = 0; current < receiver_count; ++current) { __ Jump(handlers->at(current), RelocInfo::CODE_TARGET, - eq, a2, Operand(receiver_maps->at(current))); + eq, map_reg, Operand(receiver_maps->at(current))); } __ bind(&miss); GenerateLoadMiss(masm(), kind()); // Return the generated code. - return GetCode(Code::NORMAL, factory()->empty_string(), POLYMORPHIC); + InlineCacheState state = + receiver_maps->length() > 1 ? POLYMORPHIC : MONOMORPHIC; + return GetCode(Code::IC_FRAGMENT, type, name, state); } -- 2.7.4