diff options
Diffstat (limited to 'src/ic')
31 files changed, 653 insertions, 710 deletions
diff --git a/src/ic/arm/handler-compiler-arm.cc b/src/ic/arm/handler-compiler-arm.cc index 4ed765e7..691fe3d2 100644 --- a/src/ic/arm/handler-compiler-arm.cc +++ b/src/ic/arm/handler-compiler-arm.cc @@ -111,15 +111,21 @@ void NamedStoreHandlerCompiler::GenerateStoreViaSetter( void PropertyHandlerCompiler::PushVectorAndSlot(Register vector, Register slot) { MacroAssembler* masm = this->masm(); - __ push(vector); + STATIC_ASSERT(LoadWithVectorDescriptor::kSlot < + LoadWithVectorDescriptor::kVector); + STATIC_ASSERT(StoreWithVectorDescriptor::kSlot < + StoreWithVectorDescriptor::kVector); + STATIC_ASSERT(StoreTransitionDescriptor::kSlot < + StoreTransitionDescriptor::kVector); __ push(slot); + __ push(vector); } void PropertyHandlerCompiler::PopVectorAndSlot(Register vector, Register slot) { MacroAssembler* masm = this->masm(); - __ pop(slot); __ pop(vector); + __ pop(slot); } @@ -129,6 +135,13 @@ void PropertyHandlerCompiler::DiscardVectorAndSlot() { __ add(sp, sp, Operand(2 * kPointerSize)); } +void PropertyHandlerCompiler::PushReturnAddress(Register tmp) { + // No-op. Return address is in lr register. +} + +void PropertyHandlerCompiler::PopReturnAddress(Register tmp) { + // No-op. Return address is in lr register. +} void PropertyHandlerCompiler::GenerateDictionaryNegativeLookup( MacroAssembler* masm, Label* miss_label, Register receiver, @@ -330,24 +343,6 @@ void PropertyHandlerCompiler::GenerateApiAccessorCall( __ TailCallStub(&stub); } - -static void StoreIC_PushArgs(MacroAssembler* masm) { - __ Push(StoreDescriptor::ReceiverRegister(), StoreDescriptor::NameRegister(), - StoreDescriptor::ValueRegister(), - StoreWithVectorDescriptor::SlotRegister(), - StoreWithVectorDescriptor::VectorRegister()); -} - - -void ElementHandlerCompiler::GenerateStoreSlow(MacroAssembler* masm) { - StoreIC_PushArgs(masm); - - // The slow case calls into the runtime to complete the store without causing - // an IC miss that would otherwise cause a transition to the generic stub. - __ TailCallRuntime(Runtime::kKeyedStoreIC_Slow); -} - - #undef __ #define __ ACCESS_MASM(masm()) @@ -366,12 +361,6 @@ void NamedStoreHandlerCompiler::GenerateRestoreName(Handle<Name> name) { } -void NamedStoreHandlerCompiler::RearrangeVectorAndSlot( - Register current_map, Register destination_map) { - DCHECK(false); // Not implemented. -} - - void NamedStoreHandlerCompiler::GenerateRestoreMap(Handle<Map> transition, Register map_reg, Register scratch, @@ -629,6 +618,9 @@ void NamedLoadHandlerCompiler::GenerateLoadInterceptor(Register holder_reg) { __ TailCallRuntime(Runtime::kLoadPropertyWithInterceptor); } +void NamedStoreHandlerCompiler::ZapStackArgumentsRegisterAliases() { + STATIC_ASSERT(!StoreWithVectorDescriptor::kPassLastArgsOnStack); +} Handle<Code> NamedStoreHandlerCompiler::CompileStoreCallback( Handle<JSObject> object, Handle<Name> name, Handle<AccessorInfo> callback, diff --git a/src/ic/arm/ic-arm.cc b/src/ic/arm/ic-arm.cc index fee6ebf2..10ec578f 100644 --- a/src/ic/arm/ic-arm.cc +++ b/src/ic/arm/ic-arm.cc @@ -441,10 +441,11 @@ void KeyedLoadIC::GenerateMegamorphic(MacroAssembler* masm) { static void StoreIC_PushArgs(MacroAssembler* masm) { - __ Push(StoreDescriptor::ReceiverRegister(), StoreDescriptor::NameRegister(), - StoreDescriptor::ValueRegister(), + __ Push(StoreWithVectorDescriptor::ValueRegister(), StoreWithVectorDescriptor::SlotRegister(), - StoreWithVectorDescriptor::VectorRegister()); + StoreWithVectorDescriptor::VectorRegister(), + StoreWithVectorDescriptor::ReceiverRegister(), + StoreWithVectorDescriptor::NameRegister()); } @@ -454,6 +455,13 @@ void KeyedStoreIC::GenerateMiss(MacroAssembler* masm) { __ TailCallRuntime(Runtime::kKeyedStoreIC_Miss); } +void KeyedStoreIC::GenerateSlow(MacroAssembler* masm) { + StoreIC_PushArgs(masm); + + // The slow case calls into the runtime to complete the store without causing + // an IC miss that would otherwise cause a transition to the generic stub. + __ TailCallRuntime(Runtime::kKeyedStoreIC_Slow); +} static void KeyedStoreGenerateMegamorphicHelper( MacroAssembler* masm, Label* fast_object, Label* fast_double, Label* slow, diff --git a/src/ic/arm64/handler-compiler-arm64.cc b/src/ic/arm64/handler-compiler-arm64.cc index 277b4e71..3f97fddc 100644 --- a/src/ic/arm64/handler-compiler-arm64.cc +++ b/src/ic/arm64/handler-compiler-arm64.cc @@ -20,15 +20,21 @@ namespace internal { void PropertyHandlerCompiler::PushVectorAndSlot(Register vector, Register slot) { MacroAssembler* masm = this->masm(); - __ Push(vector); + STATIC_ASSERT(LoadWithVectorDescriptor::kSlot < + LoadWithVectorDescriptor::kVector); + STATIC_ASSERT(StoreWithVectorDescriptor::kSlot < + StoreWithVectorDescriptor::kVector); + STATIC_ASSERT(StoreTransitionDescriptor::kSlot < + StoreTransitionDescriptor::kVector); __ Push(slot); + __ Push(vector); } void PropertyHandlerCompiler::PopVectorAndSlot(Register vector, Register slot) { MacroAssembler* masm = this->masm(); - __ Pop(slot); __ Pop(vector); + __ Pop(slot); } @@ -38,6 +44,13 @@ void PropertyHandlerCompiler::DiscardVectorAndSlot() { __ Drop(2); } +void PropertyHandlerCompiler::PushReturnAddress(Register tmp) { + // No-op. Return address is in lr register. +} + +void PropertyHandlerCompiler::PopReturnAddress(Register tmp) { + // No-op. Return address is in lr register. +} void PropertyHandlerCompiler::GenerateDictionaryNegativeLookup( MacroAssembler* masm, Label* miss_label, Register receiver, @@ -323,25 +336,6 @@ void NamedLoadHandlerCompiler::GenerateLoadViaGetter( __ Ret(); } - -static void StoreIC_PushArgs(MacroAssembler* masm) { - __ Push(StoreDescriptor::ReceiverRegister(), StoreDescriptor::NameRegister(), - StoreDescriptor::ValueRegister(), - StoreWithVectorDescriptor::SlotRegister(), - StoreWithVectorDescriptor::VectorRegister()); -} - - -void ElementHandlerCompiler::GenerateStoreSlow(MacroAssembler* masm) { - ASM_LOCATION("ElementHandlerCompiler::GenerateStoreSlow"); - StoreIC_PushArgs(masm); - - // The slow case calls into the runtime to complete the store without causing - // an IC miss that would otherwise cause a transition to the generic stub. - __ TailCallRuntime(Runtime::kKeyedStoreIC_Slow); -} - - #undef __ #define __ ACCESS_MASM(masm()) @@ -398,12 +392,6 @@ void NamedStoreHandlerCompiler::GenerateRestoreName(Handle<Name> name) { } -void NamedStoreHandlerCompiler::RearrangeVectorAndSlot( - Register current_map, Register destination_map) { - DCHECK(false); // Not implemented. -} - - void NamedStoreHandlerCompiler::GenerateRestoreMap(Handle<Map> transition, Register map_reg, Register scratch, @@ -664,6 +652,9 @@ void NamedLoadHandlerCompiler::GenerateLoadInterceptor(Register holder_reg) { __ TailCallRuntime(Runtime::kLoadPropertyWithInterceptor); } +void NamedStoreHandlerCompiler::ZapStackArgumentsRegisterAliases() { + STATIC_ASSERT(!StoreWithVectorDescriptor::kPassLastArgsOnStack); +} Handle<Code> NamedStoreHandlerCompiler::CompileStoreCallback( Handle<JSObject> object, Handle<Name> name, Handle<AccessorInfo> callback, diff --git a/src/ic/arm64/ic-arm64.cc b/src/ic/arm64/ic-arm64.cc index 9d66eb24..fa9d7c16 100644 --- a/src/ic/arm64/ic-arm64.cc +++ b/src/ic/arm64/ic-arm64.cc @@ -445,10 +445,11 @@ void KeyedLoadIC::GenerateMegamorphic(MacroAssembler* masm) { static void StoreIC_PushArgs(MacroAssembler* masm) { - __ Push(StoreDescriptor::ReceiverRegister(), StoreDescriptor::NameRegister(), - StoreDescriptor::ValueRegister(), + __ Push(StoreWithVectorDescriptor::ValueRegister(), StoreWithVectorDescriptor::SlotRegister(), - StoreWithVectorDescriptor::VectorRegister()); + StoreWithVectorDescriptor::VectorRegister(), + StoreWithVectorDescriptor::ReceiverRegister(), + StoreWithVectorDescriptor::NameRegister()); } @@ -458,6 +459,14 @@ void KeyedStoreIC::GenerateMiss(MacroAssembler* masm) { __ TailCallRuntime(Runtime::kKeyedStoreIC_Miss); } +void KeyedStoreIC::GenerateSlow(MacroAssembler* masm) { + ASM_LOCATION("KeyedStoreIC::GenerateSlow"); + StoreIC_PushArgs(masm); + + // The slow case calls into the runtime to complete the store without causing + // an IC miss that would otherwise cause a transition to the generic stub. + __ TailCallRuntime(Runtime::kKeyedStoreIC_Slow); +} static void KeyedStoreGenerateMegamorphicHelper( MacroAssembler* masm, Label* fast_object, Label* fast_double, Label* slow, diff --git a/src/ic/handler-compiler.cc b/src/ic/handler-compiler.cc index b6b81def..3b2e115b 100644 --- a/src/ic/handler-compiler.cc +++ b/src/ic/handler-compiler.cc @@ -129,13 +129,13 @@ Register NamedStoreHandlerCompiler::FrontendHeader(Register object_reg, Register PropertyHandlerCompiler::Frontend(Handle<Name> name) { Label miss; - if (IC::ICUseVector(kind())) { + if (IC::ShouldPushPopSlotAndVector(kind())) { PushVectorAndSlot(); } Register reg = FrontendHeader(receiver(), name, &miss, RETURN_HOLDER); FrontendFooter(name, &miss); // The footer consumes the vector and slot from the stack if miss occurs. - if (IC::ICUseVector(kind())) { + if (IC::ShouldPushPopSlotAndVector(kind())) { DiscardVectorAndSlot(); } return reg; @@ -209,12 +209,12 @@ Handle<Code> NamedLoadHandlerCompiler::CompileLoadConstant(Handle<Name> name, Handle<Code> NamedLoadHandlerCompiler::CompileLoadNonexistent( Handle<Name> name) { Label miss; - if (IC::ICUseVector(kind())) { + if (IC::ShouldPushPopSlotAndVector(kind())) { DCHECK(kind() == Code::LOAD_IC); PushVectorAndSlot(); } NonexistentFrontendHeader(name, &miss, scratch2(), scratch3()); - if (IC::ICUseVector(kind())) { + if (IC::ShouldPushPopSlotAndVector(kind())) { DiscardVectorAndSlot(); } GenerateLoadConstant(isolate()->factory()->undefined_value()); @@ -247,7 +247,7 @@ Handle<Code> NamedLoadHandlerCompiler::CompileLoadCallback( void NamedLoadHandlerCompiler::InterceptorVectorSlotPush(Register holder_reg) { - if (IC::ICUseVector(kind())) { + if (IC::ShouldPushPopSlotAndVector(kind())) { if (holder_reg.is(receiver())) { PushVectorAndSlot(); } else { @@ -260,7 +260,7 @@ void NamedLoadHandlerCompiler::InterceptorVectorSlotPush(Register holder_reg) { void NamedLoadHandlerCompiler::InterceptorVectorSlotPop(Register holder_reg, PopMode mode) { - if (IC::ICUseVector(kind())) { + if (IC::ShouldPushPopSlotAndVector(kind())) { if (mode == DISCARD) { DiscardVectorAndSlot(); } else { @@ -438,7 +438,31 @@ Handle<Code> NamedStoreHandlerCompiler::CompileStoreTransition( Handle<Map> transition, Handle<Name> name) { Label miss; - PushVectorAndSlot(); + // Ensure that the StoreTransitionStub we are going to call has the same + // number of stack arguments. This means that we don't have to adapt them + // if we decide to call the transition or miss stub. + STATIC_ASSERT(Descriptor::kStackArgumentsCount == + StoreTransitionDescriptor::kStackArgumentsCount); + STATIC_ASSERT(Descriptor::kStackArgumentsCount == 0 || + Descriptor::kStackArgumentsCount == 3); + STATIC_ASSERT(Descriptor::kParameterCount - Descriptor::kValue == + StoreTransitionDescriptor::kParameterCount - + StoreTransitionDescriptor::kValue); + STATIC_ASSERT(Descriptor::kParameterCount - Descriptor::kSlot == + StoreTransitionDescriptor::kParameterCount - + StoreTransitionDescriptor::kSlot); + STATIC_ASSERT(Descriptor::kParameterCount - Descriptor::kVector == + StoreTransitionDescriptor::kParameterCount - + StoreTransitionDescriptor::kVector); + + if (Descriptor::kPassLastArgsOnStack) { + __ LoadParameterFromStack<Descriptor>(value(), Descriptor::kValue); + } + + bool need_save_restore = IC::ShouldPushPopSlotAndVector(kind()); + if (need_save_restore) { + PushVectorAndSlot(); + } // Check that we are allowed to write this. bool is_nonexistent = holder()->map() == transition->GetBackPointer(); @@ -470,23 +494,17 @@ Handle<Code> NamedStoreHandlerCompiler::CompileStoreTransition( DCHECK(!transition->is_access_check_needed()); // Call to respective StoreTransitionStub. - bool virtual_args = StoreTransitionHelper::HasVirtualSlotArg(); - Register map_reg = StoreTransitionHelper::MapRegister(); + Register map_reg = StoreTransitionDescriptor::MapRegister(); if (details.type() == DATA_CONSTANT) { DCHECK(descriptors->GetValue(descriptor)->IsJSFunction()); - Register tmp = - virtual_args ? StoreWithVectorDescriptor::VectorRegister() : map_reg; - GenerateRestoreMap(transition, tmp, scratch2(), &miss); - GenerateConstantCheck(tmp, descriptor, value(), scratch2(), &miss); - if (virtual_args) { - // This will move the map from tmp into map_reg. - RearrangeVectorAndSlot(tmp, map_reg); - } else { + GenerateRestoreMap(transition, map_reg, scratch1(), &miss); + GenerateConstantCheck(map_reg, descriptor, value(), scratch1(), &miss); + if (need_save_restore) { PopVectorAndSlot(); } GenerateRestoreName(name); - StoreTransitionStub stub(isolate()); + StoreMapStub stub(isolate()); GenerateTailCall(masm(), stub.GetCode()); } else { @@ -498,24 +516,29 @@ Handle<Code> NamedStoreHandlerCompiler::CompileStoreTransition( Map::cast(transition->GetBackPointer())->unused_property_fields() == 0 ? StoreTransitionStub::ExtendStorageAndStoreMapAndValue : StoreTransitionStub::StoreMapAndValue; - - Register tmp = - virtual_args ? StoreWithVectorDescriptor::VectorRegister() : map_reg; - GenerateRestoreMap(transition, tmp, scratch2(), &miss); - if (virtual_args) { - RearrangeVectorAndSlot(tmp, map_reg); - } else { + GenerateRestoreMap(transition, map_reg, scratch1(), &miss); + if (need_save_restore) { PopVectorAndSlot(); } - GenerateRestoreName(name); - StoreTransitionStub stub(isolate(), - FieldIndex::ForDescriptor(*transition, descriptor), - representation, store_mode); + // We need to pass name on the stack. + PopReturnAddress(this->name()); + __ Push(name); + PushReturnAddress(this->name()); + + FieldIndex index = FieldIndex::ForDescriptor(*transition, descriptor); + __ Move(StoreNamedTransitionDescriptor::FieldOffsetRegister(), + Smi::FromInt(index.index() << kPointerSizeLog2)); + + StoreTransitionStub stub(isolate(), index.is_inobject(), representation, + store_mode); GenerateTailCall(masm(), stub.GetCode()); } - GenerateRestoreName(&miss, name); - PopVectorAndSlot(); + __ bind(&miss); + if (need_save_restore) { + PopVectorAndSlot(); + } + GenerateRestoreName(name); TailCallBuiltin(masm(), MissBuiltin(kind())); return GetCode(kind(), name); @@ -534,7 +557,10 @@ Handle<Code> NamedStoreHandlerCompiler::CompileStoreField(LookupIterator* it) { FieldType* field_type = *it->GetFieldType(); bool need_save_restore = false; if (RequiresFieldTypeChecks(field_type)) { - need_save_restore = IC::ICUseVector(kind()); + need_save_restore = IC::ShouldPushPopSlotAndVector(kind()); + if (Descriptor::kPassLastArgsOnStack) { + __ LoadParameterFromStack<Descriptor>(value(), Descriptor::kValue); + } if (need_save_restore) PushVectorAndSlot(); GenerateFieldTypeChecks(field_type, value(), &miss); if (need_save_restore) PopVectorAndSlot(); @@ -568,6 +594,9 @@ Handle<Code> NamedStoreHandlerCompiler::CompileStoreCallback( GenerateTailCall(masm(), slow_stub); } Register holder = Frontend(name); + if (Descriptor::kPassLastArgsOnStack) { + __ LoadParameterFromStack<Descriptor>(value(), Descriptor::kValue); + } GenerateApiAccessorCall(masm(), call_optimization, handle(object->map()), receiver(), scratch2(), true, value(), holder, accessor_index); @@ -601,13 +630,21 @@ Handle<Object> ElementHandlerCompiler::GetKeyedLoadHandler( TRACE_HANDLER_STATS(isolate, KeyedLoadIC_KeyedLoadSloppyArgumentsStub); return KeyedLoadSloppyArgumentsStub(isolate).GetCode(); } + bool is_js_array = instance_type == JS_ARRAY_TYPE; if (elements_kind == DICTIONARY_ELEMENTS) { + if (FLAG_tf_load_ic_stub) { + int config = KeyedLoadElementsKind::encode(elements_kind) | + KeyedLoadConvertHole::encode(false) | + KeyedLoadIsJsArray::encode(is_js_array) | + LoadHandlerTypeBit::encode(kLoadICHandlerForElements); + return handle(Smi::FromInt(config), isolate); + } TRACE_HANDLER_STATS(isolate, KeyedLoadIC_LoadDictionaryElementStub); return LoadDictionaryElementStub(isolate).GetCode(); } DCHECK(IsFastElementsKind(elements_kind) || IsFixedTypedArrayElementsKind(elements_kind)); - bool is_js_array = instance_type == JS_ARRAY_TYPE; + // TODO(jkummerow): Use IsHoleyElementsKind(elements_kind). bool convert_hole_to_undefined = is_js_array && elements_kind == FAST_HOLEY_ELEMENTS && *receiver_map == isolate->get_initial_js_array_map(elements_kind); diff --git a/src/ic/handler-compiler.h b/src/ic/handler-compiler.h index 525889b8..63ca050c 100644 --- a/src/ic/handler-compiler.h +++ b/src/ic/handler-compiler.h @@ -53,6 +53,9 @@ class PropertyHandlerCompiler : public PropertyAccessCompiler { void DiscardVectorAndSlot(); + void PushReturnAddress(Register tmp); + void PopReturnAddress(Register tmp); + // TODO(verwaest): Make non-static. static void GenerateApiAccessorCall(MacroAssembler* masm, const CallOptimization& optimization, @@ -212,13 +215,24 @@ class NamedLoadHandlerCompiler : public PropertyHandlerCompiler { class NamedStoreHandlerCompiler : public PropertyHandlerCompiler { public: + // All store handlers use StoreWithVectorDescriptor calling convention. + typedef StoreWithVectorDescriptor Descriptor; + explicit NamedStoreHandlerCompiler(Isolate* isolate, Handle<Map> map, Handle<JSObject> holder) : PropertyHandlerCompiler(isolate, Code::STORE_IC, map, holder, - kCacheOnReceiver) {} + kCacheOnReceiver) { +#ifdef DEBUG + if (Descriptor::kPassLastArgsOnStack) { + ZapStackArgumentsRegisterAliases(); + } +#endif + } virtual ~NamedStoreHandlerCompiler() {} + void ZapStackArgumentsRegisterAliases(); + Handle<Code> CompileStoreTransition(Handle<Map> transition, Handle<Name> name); Handle<Code> CompileStoreField(LookupIterator* it); @@ -249,10 +263,6 @@ class NamedStoreHandlerCompiler : public PropertyHandlerCompiler { virtual void FrontendFooter(Handle<Name> name, Label* miss); void GenerateRestoreName(Label* label, Handle<Name> name); - // Pop the vector and slot into appropriate registers, moving the map in - // the process. (This is an accomodation for register pressure on ia32). - void RearrangeVectorAndSlot(Register current_map, Register destination_map); - private: void GenerateRestoreName(Handle<Name> name); void GenerateRestoreMap(Handle<Map> transition, Register map_reg, @@ -283,8 +293,6 @@ class ElementHandlerCompiler : public PropertyHandlerCompiler { Isolate* isolate); void CompileElementHandlers(MapHandleList* receiver_maps, List<Handle<Object>>* handlers); - - static void GenerateStoreSlow(MacroAssembler* masm); }; } // namespace internal } // namespace v8 diff --git a/src/ic/ia32/handler-compiler-ia32.cc b/src/ic/ia32/handler-compiler-ia32.cc index b332f117..06c58b8a 100644 --- a/src/ic/ia32/handler-compiler-ia32.cc +++ b/src/ic/ia32/handler-compiler-ia32.cc @@ -59,15 +59,21 @@ void NamedLoadHandlerCompiler::GenerateLoadViaGetter( void PropertyHandlerCompiler::PushVectorAndSlot(Register vector, Register slot) { MacroAssembler* masm = this->masm(); - __ push(vector); + STATIC_ASSERT(LoadWithVectorDescriptor::kSlot < + LoadWithVectorDescriptor::kVector); + STATIC_ASSERT(StoreWithVectorDescriptor::kSlot < + StoreWithVectorDescriptor::kVector); + STATIC_ASSERT(StoreTransitionDescriptor::kSlot < + StoreTransitionDescriptor::kVector); __ push(slot); + __ push(vector); } void PropertyHandlerCompiler::PopVectorAndSlot(Register vector, Register slot) { MacroAssembler* masm = this->masm(); - __ pop(slot); __ pop(vector); + __ pop(slot); } @@ -77,6 +83,15 @@ void PropertyHandlerCompiler::DiscardVectorAndSlot() { __ add(esp, Immediate(2 * kPointerSize)); } +void PropertyHandlerCompiler::PushReturnAddress(Register tmp) { + MacroAssembler* masm = this->masm(); + __ push(tmp); +} + +void PropertyHandlerCompiler::PopReturnAddress(Register tmp) { + MacroAssembler* masm = this->masm(); + __ pop(tmp); +} void PropertyHandlerCompiler::GenerateDictionaryNegativeLookup( MacroAssembler* masm, Label* miss_label, Register receiver, @@ -150,12 +165,16 @@ void PropertyHandlerCompiler::GenerateApiAccessorCall( DCHECK(!accessor_holder.is(scratch)); // Copy return value. __ pop(scratch); - // receiver + + if (is_store) { + // Discard stack arguments. + __ add(esp, Immediate(StoreWithVectorDescriptor::kStackArgumentsCount * + kPointerSize)); + } + // Write the receiver and arguments to stack frame. __ push(receiver); - // Write the arguments to stack frame. if (is_store) { - DCHECK(!receiver.is(store_parameter)); - DCHECK(!scratch.is(store_parameter)); + DCHECK(!AreAliased(receiver, scratch, store_parameter)); __ push(store_parameter); } __ push(scratch); @@ -252,8 +271,13 @@ void NamedStoreHandlerCompiler::GenerateStoreViaSetter( MacroAssembler* masm, Handle<Map> map, Register receiver, Register holder, int accessor_index, int expected_arguments, Register scratch) { // ----------- S t a t e ------------- - // -- esp[0] : return address + // -- esp[12] : value + // -- esp[8] : slot + // -- esp[4] : vector + // -- esp[0] : return address // ----------------------------------- + __ LoadParameterFromStack<Descriptor>(value(), Descriptor::kValue); + { FrameScope scope(masm, StackFrame::INTERNAL); @@ -290,7 +314,14 @@ void NamedStoreHandlerCompiler::GenerateStoreViaSetter( // Restore context register. __ pop(esi); } - __ ret(0); + if (accessor_index >= 0) { + __ ret(StoreWithVectorDescriptor::kStackArgumentsCount * kPointerSize); + } else { + // If we generate a global code snippet for deoptimization only, don't try + // to drop stack arguments for the StoreIC because they are not a part of + // expression stack and deoptimizer does not reconstruct them. + __ ret(0); + } } @@ -316,32 +347,6 @@ static void CompileCallLoadPropertyWithInterceptor( __ CallRuntime(id); } - -static void StoreIC_PushArgs(MacroAssembler* masm) { - Register receiver = StoreDescriptor::ReceiverRegister(); - Register name = StoreDescriptor::NameRegister(); - Register value = StoreDescriptor::ValueRegister(); - Register slot = StoreWithVectorDescriptor::SlotRegister(); - Register vector = StoreWithVectorDescriptor::VectorRegister(); - - __ xchg(receiver, Operand(esp, 0)); - __ push(name); - __ push(value); - __ push(slot); - __ push(vector); - __ push(receiver); // which contains the return address. -} - - -void ElementHandlerCompiler::GenerateStoreSlow(MacroAssembler* masm) { - // Return address is on the stack. - StoreIC_PushArgs(masm); - - // Do tail-call to runtime routine. - __ TailCallRuntime(Runtime::kKeyedStoreIC_Slow); -} - - #undef __ #define __ ACCESS_MASM(masm()) @@ -360,19 +365,6 @@ void NamedStoreHandlerCompiler::GenerateRestoreName(Handle<Name> name) { } -void NamedStoreHandlerCompiler::RearrangeVectorAndSlot( - Register current_map, Register destination_map) { - DCHECK(destination_map.is(StoreTransitionHelper::MapRegister())); - DCHECK(current_map.is(StoreTransitionHelper::VectorRegister())); - ExternalReference virtual_slot = - ExternalReference::virtual_slot_register(isolate()); - __ mov(destination_map, current_map); - __ pop(current_map); - __ mov(Operand::StaticVariable(virtual_slot), current_map); - __ pop(current_map); // put vector in place. -} - - void NamedStoreHandlerCompiler::GenerateRestoreMap(Handle<Map> transition, Register map_reg, Register scratch, @@ -532,7 +524,7 @@ void NamedLoadHandlerCompiler::FrontendFooter(Handle<Name> name, Label* miss) { Label success; __ jmp(&success); __ bind(miss); - if (IC::ICUseVector(kind())) { + if (IC::ShouldPushPopSlotAndVector(kind())) { DCHECK(kind() == Code::LOAD_IC); PopVectorAndSlot(); } @@ -547,7 +539,7 @@ void NamedStoreHandlerCompiler::FrontendFooter(Handle<Name> name, Label* miss) { Label success; __ jmp(&success); GenerateRestoreName(miss, name); - if (IC::ICUseVector(kind())) PopVectorAndSlot(); + DCHECK(!IC::ShouldPushPopSlotAndVector(kind())); TailCallBuiltin(masm(), MissBuiltin(kind())); __ bind(&success); } @@ -641,13 +633,26 @@ void NamedLoadHandlerCompiler::GenerateLoadInterceptor(Register holder_reg) { __ TailCallRuntime(Runtime::kLoadPropertyWithInterceptor); } +void NamedStoreHandlerCompiler::ZapStackArgumentsRegisterAliases() { + // Zap register aliases of the arguments passed on the stack to ensure they + // are properly loaded by the handler (debug-only). + STATIC_ASSERT(Descriptor::kPassLastArgsOnStack); + STATIC_ASSERT(Descriptor::kStackArgumentsCount == 3); + __ mov(Descriptor::ValueRegister(), Immediate(kDebugZapValue)); + __ mov(Descriptor::SlotRegister(), Immediate(kDebugZapValue)); + __ mov(Descriptor::VectorRegister(), Immediate(kDebugZapValue)); +} Handle<Code> NamedStoreHandlerCompiler::CompileStoreCallback( Handle<JSObject> object, Handle<Name> name, Handle<AccessorInfo> callback, LanguageMode language_mode) { Register holder_reg = Frontend(name); + __ LoadParameterFromStack<Descriptor>(value(), Descriptor::kValue); __ pop(scratch1()); // remove the return address + // Discard stack arguments. + __ add(esp, Immediate(StoreWithVectorDescriptor::kStackArgumentsCount * + kPointerSize)); __ push(receiver()); __ push(holder_reg); // If the callback cannot leak, then push the callback directly, @@ -679,7 +684,7 @@ Register NamedStoreHandlerCompiler::value() { Handle<Code> NamedLoadHandlerCompiler::CompileLoadGlobal( Handle<PropertyCell> cell, Handle<Name> name, bool is_configurable) { Label miss; - if (IC::ICUseVector(kind())) { + if (IC::ShouldPushPopSlotAndVector(kind())) { PushVectorAndSlot(); } FrontendHeader(receiver(), name, &miss, DONT_RETURN_ANYTHING); @@ -701,7 +706,7 @@ Handle<Code> NamedLoadHandlerCompiler::CompileLoadGlobal( Counters* counters = isolate()->counters(); __ IncrementCounter(counters->ic_named_load_global_stub(), 1); // The code above already loads the result into the return register. - if (IC::ICUseVector(kind())) { + if (IC::ShouldPushPopSlotAndVector(kind())) { DiscardVectorAndSlot(); } __ ret(0); diff --git a/src/ic/ia32/ic-compiler-ia32.cc b/src/ic/ia32/ic-compiler-ia32.cc index d93b67bf..a52f0468 100644 --- a/src/ic/ia32/ic-compiler-ia32.cc +++ b/src/ic/ia32/ic-compiler-ia32.cc @@ -15,14 +15,21 @@ namespace internal { void PropertyICCompiler::GenerateRuntimeSetProperty( MacroAssembler* masm, LanguageMode language_mode) { - // Return address is on the stack. - DCHECK(!ebx.is(StoreDescriptor::ReceiverRegister()) && - !ebx.is(StoreDescriptor::NameRegister()) && - !ebx.is(StoreDescriptor::ValueRegister())); + typedef StoreWithVectorDescriptor Descriptor; + STATIC_ASSERT(Descriptor::kStackArgumentsCount == 3); + // ----------- S t a t e ------------- + // -- esp[12] : value + // -- esp[8] : slot + // -- esp[4] : vector + // -- esp[0] : return address + // ----------------------------------- + __ LoadParameterFromStack<Descriptor>(Descriptor::ValueRegister(), + Descriptor::kValue); + + __ mov(Operand(esp, 12), Descriptor::ReceiverRegister()); + __ mov(Operand(esp, 8), Descriptor::NameRegister()); + __ mov(Operand(esp, 4), Descriptor::ValueRegister()); __ pop(ebx); - __ push(StoreDescriptor::ReceiverRegister()); - __ push(StoreDescriptor::NameRegister()); - __ push(StoreDescriptor::ValueRegister()); __ push(Immediate(Smi::FromInt(language_mode))); __ push(ebx); // return address diff --git a/src/ic/ia32/ic-ia32.cc b/src/ic/ia32/ic-ia32.cc index 0550d92e..b7496d46 100644 --- a/src/ic/ia32/ic-ia32.cc +++ b/src/ic/ia32/ic-ia32.cc @@ -409,7 +409,7 @@ static void KeyedStoreGenerateMegamorphicHelper( } // It's irrelevant whether array is smi-only or not when writing a smi. __ mov(FixedArrayElementOperand(ebx, key), value); - __ ret(0); + __ ret(StoreWithVectorDescriptor::kStackArgumentsCount * kPointerSize); __ bind(&non_smi_value); // Escape to elements kind transition case. @@ -428,7 +428,7 @@ static void KeyedStoreGenerateMegamorphicHelper( __ mov(edx, value); // Preserve the value which is returned. __ RecordWriteArray(ebx, edx, key, kDontSaveFPRegs, EMIT_REMEMBERED_SET, OMIT_SMI_CHECK); - __ ret(0); + __ ret(StoreWithVectorDescriptor::kStackArgumentsCount * kPointerSize); __ bind(fast_double); if (check_map == kCheckMap) { @@ -457,7 +457,7 @@ static void KeyedStoreGenerateMegamorphicHelper( __ add(FieldOperand(receiver, JSArray::kLengthOffset), Immediate(Smi::FromInt(1))); } - __ ret(0); + __ ret(StoreWithVectorDescriptor::kStackArgumentsCount * kPointerSize); __ bind(&transition_smi_elements); __ mov(ebx, FieldOperand(receiver, HeapObject::kMapOffset)); @@ -504,12 +504,13 @@ static void KeyedStoreGenerateMegamorphicHelper( void KeyedStoreIC::GenerateMegamorphic(MacroAssembler* masm, LanguageMode language_mode) { + typedef StoreWithVectorDescriptor Descriptor; // Return address is on the stack. Label slow, fast_object, fast_object_grow; Label fast_double, fast_double_grow; Label array, extra, check_if_double_array, maybe_name_key, miss; - Register receiver = StoreDescriptor::ReceiverRegister(); - Register key = StoreDescriptor::NameRegister(); + Register receiver = Descriptor::ReceiverRegister(); + Register key = Descriptor::NameRegister(); DCHECK(receiver.is(edx)); DCHECK(key.is(ecx)); @@ -522,6 +523,10 @@ void KeyedStoreIC::GenerateMegamorphic(MacroAssembler* masm, __ test_b(FieldOperand(edi, Map::kBitFieldOffset), Immediate(1 << Map::kIsAccessCheckNeeded)); __ j(not_zero, &slow); + + __ LoadParameterFromStack<Descriptor>(Descriptor::ValueRegister(), + Descriptor::kValue); + // Check that the key is a smi. __ JumpIfNotSmi(key, &maybe_name_key); __ CmpInstanceType(edi, JS_ARRAY_TYPE); @@ -551,22 +556,9 @@ void KeyedStoreIC::GenerateMegamorphic(MacroAssembler* masm, __ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset)); __ JumpIfNotUniqueNameInstanceType(ebx, &slow); - - // The handlers in the stub cache expect a vector and slot. Since we won't - // change the IC from any downstream misses, a dummy vector can be used. - Handle<TypeFeedbackVector> dummy_vector = - TypeFeedbackVector::DummyVector(masm->isolate()); - int slot = dummy_vector->GetIndex( - FeedbackVectorSlot(TypeFeedbackVector::kDummyKeyedStoreICSlot)); - __ push(Immediate(Smi::FromInt(slot))); - __ push(Immediate(dummy_vector)); - masm->isolate()->store_stub_cache()->GenerateProbe(masm, receiver, key, edi, no_reg); - __ pop(StoreWithVectorDescriptor::VectorRegister()); - __ pop(StoreWithVectorDescriptor::SlotRegister()); - // Cache miss. __ jmp(&miss); @@ -705,18 +697,21 @@ void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) { } static void StoreIC_PushArgs(MacroAssembler* masm) { - Register receiver = StoreDescriptor::ReceiverRegister(); - Register name = StoreDescriptor::NameRegister(); - Register value = StoreDescriptor::ValueRegister(); - Register slot = StoreWithVectorDescriptor::SlotRegister(); - Register vector = StoreWithVectorDescriptor::VectorRegister(); - - __ xchg(receiver, Operand(esp, 0)); + Register receiver = StoreWithVectorDescriptor::ReceiverRegister(); + Register name = StoreWithVectorDescriptor::NameRegister(); + + STATIC_ASSERT(StoreWithVectorDescriptor::kStackArgumentsCount == 3); + // Current stack layout: + // - esp[12] -- value + // - esp[8] -- slot + // - esp[4] -- vector + // - esp[0] -- return address + + Register return_address = StoreWithVectorDescriptor::SlotRegister(); + __ pop(return_address); + __ push(receiver); __ push(name); - __ push(value); - __ push(slot); - __ push(vector); - __ push(receiver); // Contains the return address. + __ push(return_address); } @@ -730,32 +725,33 @@ void StoreIC::GenerateMiss(MacroAssembler* masm) { void StoreIC::GenerateNormal(MacroAssembler* masm) { + typedef StoreWithVectorDescriptor Descriptor; Label restore_miss; - Register receiver = StoreDescriptor::ReceiverRegister(); - Register name = StoreDescriptor::NameRegister(); - Register value = StoreDescriptor::ValueRegister(); - Register vector = StoreWithVectorDescriptor::VectorRegister(); - Register slot = StoreWithVectorDescriptor::SlotRegister(); - - // A lot of registers are needed for storing to slow case - // objects. Push and restore receiver but rely on - // GenerateDictionaryStore preserving the value and name. + Register receiver = Descriptor::ReceiverRegister(); + Register name = Descriptor::NameRegister(); + Register value = Descriptor::ValueRegister(); + // Since the slot and vector values are passed on the stack we can use + // respective registers as scratch registers. + Register scratch1 = Descriptor::VectorRegister(); + Register scratch2 = Descriptor::SlotRegister(); + + __ LoadParameterFromStack<Descriptor>(value, Descriptor::kValue); + + // A lot of registers are needed for storing to slow case objects. + // Push and restore receiver but rely on GenerateDictionaryStore preserving + // the value and name. __ push(receiver); - __ push(vector); - __ push(slot); - Register dictionary = ebx; + Register dictionary = receiver; __ mov(dictionary, FieldOperand(receiver, JSObject::kPropertiesOffset)); GenerateDictionaryStore(masm, &restore_miss, dictionary, name, value, - receiver, edi); - __ Drop(3); + scratch1, scratch2); + __ Drop(1); Counters* counters = masm->isolate()->counters(); __ IncrementCounter(counters->ic_store_normal_hit(), 1); - __ ret(0); + __ ret(Descriptor::kStackArgumentsCount * kPointerSize); __ bind(&restore_miss); - __ pop(slot); - __ pop(vector); __ pop(receiver); __ IncrementCounter(counters->ic_store_normal_miss(), 1); GenerateMiss(masm); @@ -770,6 +766,13 @@ void KeyedStoreIC::GenerateMiss(MacroAssembler* masm) { __ TailCallRuntime(Runtime::kKeyedStoreIC_Miss); } +void KeyedStoreIC::GenerateSlow(MacroAssembler* masm) { + // Return address is on the stack. + StoreIC_PushArgs(masm); + + // Do tail-call to runtime routine. + __ TailCallRuntime(Runtime::kKeyedStoreIC_Slow); +} #undef __ diff --git a/src/ic/ia32/stub-cache-ia32.cc b/src/ic/ia32/stub-cache-ia32.cc index 939e7fc0..82700d34 100644 --- a/src/ic/ia32/stub-cache-ia32.cc +++ b/src/ic/ia32/stub-cache-ia32.cc @@ -22,8 +22,6 @@ static void ProbeTable(StubCache* stub_cache, MacroAssembler* masm, ExternalReference key_offset(stub_cache->key_reference(table)); ExternalReference value_offset(stub_cache->value_reference(table)); ExternalReference map_offset(stub_cache->map_reference(table)); - ExternalReference virtual_register = - ExternalReference::virtual_handler_register(masm->isolate()); Label miss; Code::Kind ic_kind = stub_cache->ic_kind(); @@ -55,19 +53,15 @@ static void ProbeTable(StubCache* stub_cache, MacroAssembler* masm, } #endif - // The vector and slot were pushed onto the stack before starting the - // probe, and need to be dropped before calling the handler. if (is_vector_store) { - // The overlap here is rather embarrassing. One does what one must. - Register vector = StoreWithVectorDescriptor::VectorRegister(); + // The value, vector and slot were passed to the IC on the stack and + // they are still there. So we can just jump to the handler. DCHECK(extra.is(StoreWithVectorDescriptor::SlotRegister())); __ add(extra, Immediate(Code::kHeaderSize - kHeapObjectTag)); - __ pop(vector); - __ mov(Operand::StaticVariable(virtual_register), extra); - __ pop(extra); // Pop "slot". - // Jump to the first instruction in the code stub. - __ jmp(Operand::StaticVariable(virtual_register)); + __ jmp(extra); } else { + // The vector and slot were pushed onto the stack before starting the + // probe, and need to be dropped before calling the handler. __ pop(LoadWithVectorDescriptor::VectorRegister()); __ pop(LoadDescriptor::SlotRegister()); __ add(extra, Immediate(Code::kHeaderSize - kHeapObjectTag)); @@ -110,19 +104,10 @@ static void ProbeTable(StubCache* stub_cache, MacroAssembler* masm, // Jump to the first instruction in the code stub. if (is_vector_store) { - // The vector and slot were pushed onto the stack before starting the - // probe, and need to be dropped before calling the handler. - Register vector = StoreWithVectorDescriptor::VectorRegister(); DCHECK(offset.is(StoreWithVectorDescriptor::SlotRegister())); - __ add(offset, Immediate(Code::kHeaderSize - kHeapObjectTag)); - __ mov(Operand::StaticVariable(virtual_register), offset); - __ pop(vector); - __ pop(offset); // Pop "slot". - __ jmp(Operand::StaticVariable(virtual_register)); - } else { - __ add(offset, Immediate(Code::kHeaderSize - kHeapObjectTag)); - __ jmp(offset); } + __ add(offset, Immediate(Code::kHeaderSize - kHeapObjectTag)); + __ jmp(offset); // Pop at miss. __ bind(&miss); diff --git a/src/ic/ic-inl.h b/src/ic/ic-inl.h index f77c40a3..4fc8ada8 100644 --- a/src/ic/ic-inl.h +++ b/src/ic/ic-inl.h @@ -7,7 +7,6 @@ #include "src/ic/ic.h" -#include "src/compiler.h" #include "src/debug/debug.h" #include "src/macro-assembler.h" #include "src/prototype.h" diff --git a/src/ic/ic-state.cc b/src/ic/ic-state.cc index d157c926..ea1f16c8 100644 --- a/src/ic/ic-state.cc +++ b/src/ic/ic-state.cc @@ -189,15 +189,14 @@ void BinaryOpICState::GenerateAheadOfTime( #undef GENERATE } - -Type* BinaryOpICState::GetResultType() const { +AstType* BinaryOpICState::GetResultType() const { Kind result_kind = result_kind_; if (HasSideEffects()) { result_kind = NONE; } else if (result_kind == GENERIC && op_ == Token::ADD) { - return Type::NumberOrString(); + return AstType::NumberOrString(); } else if (result_kind == NUMBER && op_ == Token::SHR) { - return Type::Unsigned32(); + return AstType::Unsigned32(); } DCHECK_NE(GENERIC, result_kind); return KindToType(result_kind); @@ -318,20 +317,20 @@ const char* BinaryOpICState::KindToString(Kind kind) { // static -Type* BinaryOpICState::KindToType(Kind kind) { +AstType* BinaryOpICState::KindToType(Kind kind) { switch (kind) { case NONE: - return Type::None(); + return AstType::None(); case SMI: - return Type::SignedSmall(); + return AstType::SignedSmall(); case INT32: - return Type::Signed32(); + return AstType::Signed32(); case NUMBER: - return Type::Number(); + return AstType::Number(); case STRING: - return Type::String(); + return AstType::String(); case GENERIC: - return Type::Any(); + return AstType::Any(); } UNREACHABLE(); return NULL; @@ -365,29 +364,28 @@ const char* CompareICState::GetStateName(State state) { return NULL; } - -Type* CompareICState::StateToType(Zone* zone, State state, Handle<Map> map) { +AstType* CompareICState::StateToType(Zone* zone, State state, Handle<Map> map) { switch (state) { case UNINITIALIZED: - return Type::None(); + return AstType::None(); case BOOLEAN: - return Type::Boolean(); + return AstType::Boolean(); case SMI: - return Type::SignedSmall(); + return AstType::SignedSmall(); case NUMBER: - return Type::Number(); + return AstType::Number(); case STRING: - return Type::String(); + return AstType::String(); case INTERNALIZED_STRING: - return Type::InternalizedString(); + return AstType::InternalizedString(); case UNIQUE_NAME: - return Type::UniqueName(); + return AstType::UniqueName(); case RECEIVER: - return Type::Receiver(); + return AstType::Receiver(); case KNOWN_RECEIVER: - return map.is_null() ? Type::Receiver() : Type::Class(map, zone); + return map.is_null() ? AstType::Receiver() : AstType::Class(map, zone); case GENERIC: - return Type::Any(); + return AstType::Any(); } UNREACHABLE(); return NULL; diff --git a/src/ic/ic-state.h b/src/ic/ic-state.h index 6888a7ab..38be57ac 100644 --- a/src/ic/ic-state.h +++ b/src/ic/ic-state.h @@ -6,6 +6,7 @@ #define V8_IC_STATE_H_ #include "src/macro-assembler.h" +#include "src/parsing/token.h" namespace v8 { namespace internal { @@ -120,9 +121,9 @@ class BinaryOpICState final BASE_EMBEDDED { Token::Value op() const { return op_; } Maybe<int> fixed_right_arg() const { return fixed_right_arg_; } - Type* GetLeftType() const { return KindToType(left_kind_); } - Type* GetRightType() const { return KindToType(right_kind_); } - Type* GetResultType() const; + AstType* GetLeftType() const { return KindToType(left_kind_); } + AstType* GetRightType() const { return KindToType(right_kind_); } + AstType* GetResultType() const; void Update(Handle<Object> left, Handle<Object> right, Handle<Object> result); @@ -140,7 +141,7 @@ class BinaryOpICState final BASE_EMBEDDED { Kind UpdateKind(Handle<Object> object, Kind kind) const; static const char* KindToString(Kind kind); - static Type* KindToType(Kind kind); + static AstType* KindToType(Kind kind); static bool KindMaybeSmi(Kind kind) { return (kind >= SMI && kind <= NUMBER) || kind == GENERIC; } @@ -202,8 +203,8 @@ class CompareICState { GENERIC }; - static Type* StateToType(Zone* zone, State state, - Handle<Map> map = Handle<Map>()); + static AstType* StateToType(Zone* zone, State state, + Handle<Map> map = Handle<Map>()); static State NewInputState(State old_state, Handle<Object> value); diff --git a/src/ic/ic.cc b/src/ic/ic.cc index b72791aa..0e751bd3 100644 --- a/src/ic/ic.cc +++ b/src/ic/ic.cc @@ -183,6 +183,19 @@ IC::IC(FrameDepth depth, Isolate* isolate, FeedbackNexus* nexus) extra_ic_state_ = target->extra_ic_state(); } +// The ICs that don't pass slot and vector through the stack have to +// save/restore them in the dispatcher. +bool IC::ShouldPushPopSlotAndVector(Code::Kind kind) { + if (kind == Code::LOAD_IC || kind == Code::LOAD_GLOBAL_IC || + kind == Code::KEYED_LOAD_IC || kind == Code::CALL_IC) { + return true; + } + if (kind == Code::STORE_IC || kind == Code::KEYED_STORE_IC) { + return !StoreWithVectorDescriptor::kPassLastArgsOnStack; + } + return false; +} + InlineCacheState IC::StateFromCode(Code* code) { Isolate* isolate = code->GetIsolate(); switch (code->kind()) { @@ -231,13 +244,6 @@ Code* IC::GetCode() const { return code; } - -bool IC::AddressIsOptimizedCode() const { - Code* host = - isolate()->inner_pointer_to_code_cache()->GetCacheEntry(address())->code; - return host->kind() == Code::OPTIMIZED_FUNCTION; -} - static void LookupForRead(LookupIterator* it) { for (; it->IsFound(); it->Next()) { switch (it->state()) { @@ -270,7 +276,7 @@ static void LookupForRead(LookupIterator* it) { } } -bool IC::ShouldRecomputeHandler(Handle<Object> receiver, Handle<String> name) { +bool IC::ShouldRecomputeHandler(Handle<String> name) { if (!RecomputeHandlerForName(name)) return false; DCHECK(UseVector()); @@ -320,7 +326,7 @@ void IC::UpdateState(Handle<Object> receiver, Handle<Object> name) { // Remove the target from the code cache if it became invalid // because of changes in the prototype chain to avoid hitting it // again. - if (ShouldRecomputeHandler(receiver, Handle<String>::cast(name))) { + if (ShouldRecomputeHandler(Handle<String>::cast(name))) { MarkRecomputeHandler(name); } } @@ -728,7 +734,6 @@ bool IC::UpdatePolymorphicIC(Handle<Name> name, Handle<Object> code) { number_of_valid_maps++; if (number_of_valid_maps > 1 && is_keyed()) return false; - Handle<Code> ic; if (number_of_valid_maps == 1) { ConfigureVectorState(name, receiver_map(), code); } else { @@ -1413,17 +1418,18 @@ MaybeHandle<Object> KeyedLoadIC::Load(Handle<Object> object, Object); } else if (FLAG_use_ic && !object->IsAccessCheckNeeded() && !object->IsJSValue()) { - if (object->IsJSObject() || (object->IsString() && key->IsNumber())) { - Handle<HeapObject> receiver = Handle<HeapObject>::cast(object); - if (object->IsString() || key->IsSmi()) UpdateLoadElement(receiver); + if ((object->IsJSObject() && key->IsSmi()) || + (object->IsString() && key->IsNumber())) { + UpdateLoadElement(Handle<HeapObject>::cast(object)); + TRACE_IC("LoadIC", key); } } if (!is_vector_set()) { ConfigureVectorState(MEGAMORPHIC, key); TRACE_GENERIC_IC(isolate(), "KeyedLoadIC", "set generic"); + TRACE_IC("LoadIC", key); } - TRACE_IC("LoadIC", key); if (!load_handle.is_null()) return load_handle; @@ -2237,7 +2243,8 @@ void CallIC::HandleMiss(Handle<Object> function) { RUNTIME_FUNCTION(Runtime_CallIC_Miss) { TimerEventScope<TimerEventIcMiss> timer(isolate); HandleScope scope(isolate); - DCHECK(args.length() == 3); + DCHECK_EQ(3, args.length()); + // Runtime functions don't follow the IC's calling convention. Handle<Object> function = args.at<Object>(0); Handle<TypeFeedbackVector> vector = args.at<TypeFeedbackVector>(1); Handle<Smi> slot = args.at<Smi>(2); @@ -2253,9 +2260,9 @@ RUNTIME_FUNCTION(Runtime_CallIC_Miss) { RUNTIME_FUNCTION(Runtime_LoadIC_Miss) { TimerEventScope<TimerEventIcMiss> timer(isolate); HandleScope scope(isolate); - Handle<Object> receiver = args.at<Object>(0); - DCHECK_EQ(4, args.length()); + // Runtime functions don't follow the IC's calling convention. + Handle<Object> receiver = args.at<Object>(0); Handle<Smi> slot = args.at<Smi>(2); Handle<TypeFeedbackVector> vector = args.at<TypeFeedbackVector>(3); FeedbackVectorSlot vector_slot = vector->ToSlot(slot->value()); @@ -2294,6 +2301,7 @@ RUNTIME_FUNCTION(Runtime_LoadGlobalIC_Miss) { TimerEventScope<TimerEventIcMiss> timer(isolate); HandleScope scope(isolate); DCHECK_EQ(2, args.length()); + // Runtime functions don't follow the IC's calling convention. Handle<JSGlobalObject> global = isolate->global_object(); Handle<Smi> slot = args.at<Smi>(0); Handle<TypeFeedbackVector> vector = args.at<TypeFeedbackVector>(1); @@ -2364,10 +2372,10 @@ RUNTIME_FUNCTION(Runtime_LoadGlobalIC_Slow) { RUNTIME_FUNCTION(Runtime_KeyedLoadIC_Miss) { TimerEventScope<TimerEventIcMiss> timer(isolate); HandleScope scope(isolate); + DCHECK_EQ(4, args.length()); + // Runtime functions don't follow the IC's calling convention. Handle<Object> receiver = args.at<Object>(0); Handle<Object> key = args.at<Object>(1); - - DCHECK(args.length() == 4); Handle<Smi> slot = args.at<Smi>(2); Handle<TypeFeedbackVector> vector = args.at<TypeFeedbackVector>(3); FeedbackVectorSlot vector_slot = vector->ToSlot(slot->value()); @@ -2381,8 +2389,8 @@ RUNTIME_FUNCTION(Runtime_KeyedLoadIC_Miss) { RUNTIME_FUNCTION(Runtime_KeyedLoadIC_MissFromStubFailure) { TimerEventScope<TimerEventIcMiss> timer(isolate); HandleScope scope(isolate); - DCHECK_EQ(4, args.length()); typedef LoadWithVectorDescriptor Descriptor; + DCHECK_EQ(Descriptor::kParameterCount, args.length()); Handle<Object> receiver = args.at<Object>(Descriptor::kReceiver); Handle<Object> key = args.at<Object>(Descriptor::kName); Handle<Smi> slot = args.at<Smi>(Descriptor::kSlot); @@ -2400,13 +2408,13 @@ RUNTIME_FUNCTION(Runtime_KeyedLoadIC_MissFromStubFailure) { RUNTIME_FUNCTION(Runtime_StoreIC_Miss) { TimerEventScope<TimerEventIcMiss> timer(isolate); HandleScope scope(isolate); - Handle<Object> receiver = args.at<Object>(0); - Handle<Name> key = args.at<Name>(1); - Handle<Object> value = args.at<Object>(2); - - DCHECK(args.length() == 5 || args.length() == 6); - Handle<Smi> slot = args.at<Smi>(3); - Handle<TypeFeedbackVector> vector = args.at<TypeFeedbackVector>(4); + DCHECK_EQ(5, args.length()); + // Runtime functions don't follow the IC's calling convention. + Handle<Object> value = args.at<Object>(0); + Handle<Smi> slot = args.at<Smi>(1); + Handle<TypeFeedbackVector> vector = args.at<TypeFeedbackVector>(2); + Handle<Object> receiver = args.at<Object>(3); + Handle<Name> key = args.at<Name>(4); FeedbackVectorSlot vector_slot = vector->ToSlot(slot->value()); if (vector->GetKind(vector_slot) == FeedbackVectorSlotKind::STORE_IC) { StoreICNexus nexus(vector, vector_slot); @@ -2424,88 +2432,17 @@ RUNTIME_FUNCTION(Runtime_StoreIC_Miss) { } -RUNTIME_FUNCTION(Runtime_StoreIC_MissFromStubFailure) { - TimerEventScope<TimerEventIcMiss> timer(isolate); - HandleScope scope(isolate); - DCHECK_EQ(5, args.length()); - typedef StoreWithVectorDescriptor Descriptor; - Handle<Object> receiver = args.at<Object>(Descriptor::kReceiver); - Handle<Name> key = args.at<Name>(Descriptor::kName); - Handle<Object> value = args.at<Object>(Descriptor::kValue); - Handle<Smi> slot = args.at<Smi>(Descriptor::kSlot); - Handle<TypeFeedbackVector> vector = - args.at<TypeFeedbackVector>(Descriptor::kVector); - - FeedbackVectorSlot vector_slot = vector->ToSlot(slot->value()); - if (vector->GetKind(vector_slot) == FeedbackVectorSlotKind::STORE_IC) { - StoreICNexus nexus(vector, vector_slot); - StoreIC ic(IC::EXTRA_CALL_FRAME, isolate, &nexus); - ic.UpdateState(receiver, key); - RETURN_RESULT_OR_FAILURE(isolate, ic.Store(receiver, key, value)); - } else { - DCHECK_EQ(FeedbackVectorSlotKind::KEYED_STORE_IC, - vector->GetKind(vector_slot)); - KeyedStoreICNexus nexus(vector, vector_slot); - KeyedStoreIC ic(IC::EXTRA_CALL_FRAME, isolate, &nexus); - ic.UpdateState(receiver, key); - RETURN_RESULT_OR_FAILURE(isolate, ic.Store(receiver, key, value)); - } -} - -RUNTIME_FUNCTION(Runtime_TransitionStoreIC_MissFromStubFailure) { - TimerEventScope<TimerEventIcMiss> timer(isolate); - HandleScope scope(isolate); - Handle<Object> receiver = args.at<Object>(0); - Handle<Name> key = args.at<Name>(1); - Handle<Object> value = args.at<Object>(2); - - int length = args.length(); - DCHECK(length == 5 || length == 6); - // TODO(ishell): use VectorStoreTransitionDescriptor indices here and update - // this comment: - // - // We might have slot and vector, for a normal miss (slot(3), vector(4)). - // Or, map and vector for a transitioning store miss (map(3), vector(4)). - // In this case, we need to recover the slot from a virtual register. - // If length == 6, then a map is included (map(3), slot(4), vector(5)). - Handle<Smi> slot; - Handle<TypeFeedbackVector> vector; - if (length == 5) { - vector = args.at<TypeFeedbackVector>(4); - slot = handle( - *reinterpret_cast<Smi**>(isolate->virtual_slot_register_address()), - isolate); - } else { - vector = args.at<TypeFeedbackVector>(5); - slot = args.at<Smi>(4); - } - - FeedbackVectorSlot vector_slot = vector->ToSlot(slot->value()); - if (vector->GetKind(vector_slot) == FeedbackVectorSlotKind::STORE_IC) { - StoreICNexus nexus(vector, vector_slot); - StoreIC ic(IC::EXTRA_CALL_FRAME, isolate, &nexus); - ic.UpdateState(receiver, key); - RETURN_RESULT_OR_FAILURE(isolate, ic.Store(receiver, key, value)); - } else { - DCHECK_EQ(FeedbackVectorSlotKind::KEYED_STORE_IC, - vector->GetKind(vector_slot)); - KeyedStoreICNexus nexus(vector, vector_slot); - KeyedStoreIC ic(IC::EXTRA_CALL_FRAME, isolate, &nexus); - ic.UpdateState(receiver, key); - RETURN_RESULT_OR_FAILURE(isolate, ic.Store(receiver, key, value)); - } -} - // Used from ic-<arch>.cc. RUNTIME_FUNCTION(Runtime_KeyedStoreIC_Miss) { TimerEventScope<TimerEventIcMiss> timer(isolate); HandleScope scope(isolate); DCHECK_EQ(5, args.length()); - Handle<Object> receiver = args.at<Object>(0); - Handle<Object> key = args.at<Object>(1); - Handle<Object> value = args.at<Object>(2); - Handle<Smi> slot = args.at<Smi>(3); - Handle<TypeFeedbackVector> vector = args.at<TypeFeedbackVector>(4); + // Runtime functions don't follow the IC's calling convention. + Handle<Object> value = args.at<Object>(0); + Handle<Smi> slot = args.at<Smi>(1); + Handle<TypeFeedbackVector> vector = args.at<TypeFeedbackVector>(2); + Handle<Object> receiver = args.at<Object>(3); + Handle<Object> key = args.at<Object>(4); FeedbackVectorSlot vector_slot = vector->ToSlot(slot->value()); KeyedStoreICNexus nexus(vector, vector_slot); KeyedStoreIC ic(IC::NO_EXTRA_FRAME, isolate, &nexus); @@ -2514,31 +2451,14 @@ RUNTIME_FUNCTION(Runtime_KeyedStoreIC_Miss) { } -RUNTIME_FUNCTION(Runtime_KeyedStoreIC_MissFromStubFailure) { - TimerEventScope<TimerEventIcMiss> timer(isolate); - HandleScope scope(isolate); - DCHECK_EQ(5, args.length()); - typedef StoreWithVectorDescriptor Descriptor; - Handle<Object> receiver = args.at<Object>(Descriptor::kReceiver); - Handle<Object> key = args.at<Object>(Descriptor::kName); - Handle<Object> value = args.at<Object>(Descriptor::kValue); - Handle<Smi> slot = args.at<Smi>(Descriptor::kSlot); - Handle<TypeFeedbackVector> vector = - args.at<TypeFeedbackVector>(Descriptor::kVector); - FeedbackVectorSlot vector_slot = vector->ToSlot(slot->value()); - KeyedStoreICNexus nexus(vector, vector_slot); - KeyedStoreIC ic(IC::EXTRA_CALL_FRAME, isolate, &nexus); - ic.UpdateState(receiver, key); - RETURN_RESULT_OR_FAILURE(isolate, ic.Store(receiver, key, value)); -} - - RUNTIME_FUNCTION(Runtime_KeyedStoreIC_Slow) { HandleScope scope(isolate); DCHECK_EQ(5, args.length()); - Handle<Object> object = args.at<Object>(0); - Handle<Object> key = args.at<Object>(1); - Handle<Object> value = args.at<Object>(2); + // Runtime functions don't follow the IC's calling convention. + Handle<Object> value = args.at<Object>(0); + // slot and vector parameters are not used. + Handle<Object> object = args.at<Object>(3); + Handle<Object> key = args.at<Object>(4); LanguageMode language_mode; KeyedStoreICNexus nexus(isolate); KeyedStoreIC ic(IC::NO_EXTRA_FRAME, isolate, &nexus); @@ -2552,16 +2472,14 @@ RUNTIME_FUNCTION(Runtime_KeyedStoreIC_Slow) { RUNTIME_FUNCTION(Runtime_ElementsTransitionAndStoreIC_Miss) { TimerEventScope<TimerEventIcMiss> timer(isolate); HandleScope scope(isolate); - // Length == 5 or 6, depending on whether the vector slot - // is passed in a virtual register or not. - DCHECK(args.length() == 5 || args.length() == 6); + // Runtime functions don't follow the IC's calling convention. Handle<Object> object = args.at<Object>(0); Handle<Object> key = args.at<Object>(1); Handle<Object> value = args.at<Object>(2); Handle<Map> map = args.at<Map>(3); LanguageMode language_mode; KeyedStoreICNexus nexus(isolate); - KeyedStoreIC ic(IC::EXTRA_CALL_FRAME, isolate, &nexus); + KeyedStoreIC ic(IC::NO_EXTRA_FRAME, isolate, &nexus); language_mode = ic.language_mode(); if (object->IsJSObject()) { JSObject::TransitionElementsKind(Handle<JSObject>::cast(object), @@ -3000,35 +2918,5 @@ RUNTIME_FUNCTION(Runtime_LoadElementWithInterceptor) { return *result; } - - -RUNTIME_FUNCTION(Runtime_LoadIC_MissFromStubFailure) { - TimerEventScope<TimerEventIcMiss> timer(isolate); - HandleScope scope(isolate); - DCHECK_EQ(4, args.length()); - typedef LoadWithVectorDescriptor Descriptor; - Handle<Object> receiver = args.at<Object>(Descriptor::kReceiver); - Handle<Name> key = args.at<Name>(Descriptor::kName); - Handle<Smi> slot = args.at<Smi>(Descriptor::kSlot); - Handle<TypeFeedbackVector> vector = - args.at<TypeFeedbackVector>(Descriptor::kVector); - FeedbackVectorSlot vector_slot = vector->ToSlot(slot->value()); - // A monomorphic or polymorphic KeyedLoadIC with a string key can call the - // LoadIC miss handler if the handler misses. Since the vector Nexus is - // set up outside the IC, handle that here. - if (vector->GetKind(vector_slot) == FeedbackVectorSlotKind::LOAD_IC) { - LoadICNexus nexus(vector, vector_slot); - LoadIC ic(IC::EXTRA_CALL_FRAME, isolate, &nexus); - ic.UpdateState(receiver, key); - RETURN_RESULT_OR_FAILURE(isolate, ic.Load(receiver, key)); - } else { - DCHECK_EQ(FeedbackVectorSlotKind::KEYED_LOAD_IC, - vector->GetKind(vector_slot)); - KeyedLoadICNexus nexus(vector, vector_slot); - KeyedLoadIC ic(IC::EXTRA_CALL_FRAME, isolate, &nexus); - ic.UpdateState(receiver, key); - RETURN_RESULT_OR_FAILURE(isolate, ic.Load(receiver, key)); - } -} } // namespace internal } // namespace v8 diff --git a/src/ic/ic.h b/src/ic/ic.h index 35f38444..bf395f1f 100644 --- a/src/ic/ic.h +++ b/src/ic/ic.h @@ -75,6 +75,10 @@ class IC { kind == Code::STORE_IC || kind == Code::KEYED_STORE_IC; } + // The ICs that don't pass slot and vector through the stack have to + // save/restore them in the dispatcher. + static bool ShouldPushPopSlotAndVector(Code::Kind kind); + static InlineCacheState StateFromCode(Code* code); protected: @@ -87,7 +91,6 @@ class IC { // Get the code object of the caller. Code* GetCode() const; - bool AddressIsOptimizedCode() const; inline bool AddressIsDeoptimizedCode() const; inline static bool AddressIsDeoptimizedCode(Isolate* isolate, Address address); @@ -168,7 +171,7 @@ class IC { kind_ == Code::KEYED_STORE_IC); return kind_; } - bool ShouldRecomputeHandler(Handle<Object> receiver, Handle<String> name); + bool ShouldRecomputeHandler(Handle<String> name); ExtraICState extra_ic_state() const { return extra_ic_state_; } diff --git a/src/ic/mips/handler-compiler-mips.cc b/src/ic/mips/handler-compiler-mips.cc index f4e0f0ba..df7a0df1 100644 --- a/src/ic/mips/handler-compiler-mips.cc +++ b/src/ic/mips/handler-compiler-mips.cc @@ -107,13 +107,19 @@ void NamedStoreHandlerCompiler::GenerateStoreViaSetter( void PropertyHandlerCompiler::PushVectorAndSlot(Register vector, Register slot) { MacroAssembler* masm = this->masm(); - __ Push(vector, slot); + STATIC_ASSERT(LoadWithVectorDescriptor::kSlot < + LoadWithVectorDescriptor::kVector); + STATIC_ASSERT(StoreWithVectorDescriptor::kSlot < + StoreWithVectorDescriptor::kVector); + STATIC_ASSERT(StoreTransitionDescriptor::kSlot < + StoreTransitionDescriptor::kVector); + __ Push(slot, vector); } void PropertyHandlerCompiler::PopVectorAndSlot(Register vector, Register slot) { MacroAssembler* masm = this->masm(); - __ Pop(vector, slot); + __ Pop(slot, vector); } @@ -123,6 +129,13 @@ void PropertyHandlerCompiler::DiscardVectorAndSlot() { __ Addu(sp, sp, Operand(2 * kPointerSize)); } +void PropertyHandlerCompiler::PushReturnAddress(Register tmp) { + // No-op. Return address is in ra register. +} + +void PropertyHandlerCompiler::PopReturnAddress(Register tmp) { + // No-op. Return address is in ra register. +} void PropertyHandlerCompiler::GenerateDictionaryNegativeLookup( MacroAssembler* masm, Label* miss_label, Register receiver, @@ -317,24 +330,6 @@ void PropertyHandlerCompiler::GenerateApiAccessorCall( __ TailCallStub(&stub); } - -static void StoreIC_PushArgs(MacroAssembler* masm) { - __ Push(StoreDescriptor::ReceiverRegister(), StoreDescriptor::NameRegister(), - StoreDescriptor::ValueRegister(), - StoreWithVectorDescriptor::SlotRegister(), - StoreWithVectorDescriptor::VectorRegister()); -} - - -void ElementHandlerCompiler::GenerateStoreSlow(MacroAssembler* masm) { - StoreIC_PushArgs(masm); - - // The slow case calls into the runtime to complete the store without causing - // an IC miss that would otherwise cause a transition to the generic stub. - __ TailCallRuntime(Runtime::kKeyedStoreIC_Slow); -} - - #undef __ #define __ ACCESS_MASM(masm()) @@ -353,12 +348,6 @@ void NamedStoreHandlerCompiler::GenerateRestoreName(Handle<Name> name) { } -void NamedStoreHandlerCompiler::RearrangeVectorAndSlot( - Register current_map, Register destination_map) { - DCHECK(false); // Not implemented. -} - - void NamedStoreHandlerCompiler::GenerateRestoreMap(Handle<Map> transition, Register map_reg, Register scratch, @@ -615,6 +604,9 @@ void NamedLoadHandlerCompiler::GenerateLoadInterceptor(Register holder_reg) { __ TailCallRuntime(Runtime::kLoadPropertyWithInterceptor); } +void NamedStoreHandlerCompiler::ZapStackArgumentsRegisterAliases() { + STATIC_ASSERT(!StoreWithVectorDescriptor::kPassLastArgsOnStack); +} Handle<Code> NamedStoreHandlerCompiler::CompileStoreCallback( Handle<JSObject> object, Handle<Name> name, Handle<AccessorInfo> callback, @@ -675,7 +667,7 @@ Handle<Code> NamedLoadHandlerCompiler::CompileLoadGlobal( DiscardVectorAndSlot(); } __ Ret(USE_DELAY_SLOT); - __ mov(v0, result); + __ Move(v0, result); // Ensure the stub returns correct value. FrontendFooter(name, &miss); diff --git a/src/ic/mips/ic-mips.cc b/src/ic/mips/ic-mips.cc index 3a28b13b..ce9e3d94 100644 --- a/src/ic/mips/ic-mips.cc +++ b/src/ic/mips/ic-mips.cc @@ -494,7 +494,8 @@ static void KeyedStoreGenerateMegamorphicHelper( __ Addu(address, elements, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); __ Lsa(address, address, key, kPointerSizeLog2 - kSmiTagSize); __ sw(value, MemOperand(address)); - __ Ret(); + __ Ret(USE_DELAY_SLOT); + __ Move(v0, value); // Ensure the stub returns correct value. __ bind(&non_smi_value); // Escape to elements kind transition case. @@ -514,7 +515,8 @@ static void KeyedStoreGenerateMegamorphicHelper( __ mov(scratch, value); // Preserve the value which is returned. __ RecordWrite(elements, address, scratch, kRAHasNotBeenSaved, kDontSaveFPRegs, EMIT_REMEMBERED_SET, OMIT_SMI_CHECK); - __ Ret(); + __ Ret(USE_DELAY_SLOT); + __ Move(v0, value); // Ensure the stub returns correct value. __ bind(fast_double); if (check_map == kCheckMap) { @@ -543,7 +545,8 @@ static void KeyedStoreGenerateMegamorphicHelper( __ Addu(scratch, key, Operand(Smi::FromInt(1))); __ sw(scratch, FieldMemOperand(receiver, JSArray::kLengthOffset)); } - __ Ret(); + __ Ret(USE_DELAY_SLOT); + __ Move(v0, value); // Ensure the stub returns correct value. __ bind(&transition_smi_elements); // Transition the array appropriately depending on the value type. @@ -710,10 +713,11 @@ void KeyedStoreIC::GenerateMegamorphic(MacroAssembler* masm, static void StoreIC_PushArgs(MacroAssembler* masm) { - __ Push(StoreDescriptor::ReceiverRegister(), StoreDescriptor::NameRegister(), - StoreDescriptor::ValueRegister(), + __ Push(StoreWithVectorDescriptor::ValueRegister(), StoreWithVectorDescriptor::SlotRegister(), - StoreWithVectorDescriptor::VectorRegister()); + StoreWithVectorDescriptor::VectorRegister(), + StoreWithVectorDescriptor::ReceiverRegister(), + StoreWithVectorDescriptor::NameRegister()); } @@ -723,6 +727,14 @@ void KeyedStoreIC::GenerateMiss(MacroAssembler* masm) { __ TailCallRuntime(Runtime::kKeyedStoreIC_Miss); } +void KeyedStoreIC::GenerateSlow(MacroAssembler* masm) { + StoreIC_PushArgs(masm); + + // The slow case calls into the runtime to complete the store without causing + // an IC miss that would otherwise cause a transition to the generic stub. + __ TailCallRuntime(Runtime::kKeyedStoreIC_Slow); +} + void StoreIC::GenerateMiss(MacroAssembler* masm) { StoreIC_PushArgs(masm); @@ -748,7 +760,8 @@ void StoreIC::GenerateNormal(MacroAssembler* masm) { GenerateDictionaryStore(masm, &miss, dictionary, name, value, t2, t5); Counters* counters = masm->isolate()->counters(); __ IncrementCounter(counters->ic_store_normal_hit(), 1, t2, t5); - __ Ret(); + __ Ret(USE_DELAY_SLOT); + __ Move(v0, value); // Ensure the stub returns correct value. __ bind(&miss); __ IncrementCounter(counters->ic_store_normal_miss(), 1, t2, t5); diff --git a/src/ic/mips64/handler-compiler-mips64.cc b/src/ic/mips64/handler-compiler-mips64.cc index 53b097f8..2190f6d6 100644 --- a/src/ic/mips64/handler-compiler-mips64.cc +++ b/src/ic/mips64/handler-compiler-mips64.cc @@ -107,13 +107,19 @@ void NamedStoreHandlerCompiler::GenerateStoreViaSetter( void PropertyHandlerCompiler::PushVectorAndSlot(Register vector, Register slot) { MacroAssembler* masm = this->masm(); - __ Push(vector, slot); + STATIC_ASSERT(LoadWithVectorDescriptor::kSlot < + LoadWithVectorDescriptor::kVector); + STATIC_ASSERT(StoreWithVectorDescriptor::kSlot < + StoreWithVectorDescriptor::kVector); + STATIC_ASSERT(StoreTransitionDescriptor::kSlot < + StoreTransitionDescriptor::kVector); + __ Push(slot, vector); } void PropertyHandlerCompiler::PopVectorAndSlot(Register vector, Register slot) { MacroAssembler* masm = this->masm(); - __ Pop(vector, slot); + __ Pop(slot, vector); } @@ -123,6 +129,13 @@ void PropertyHandlerCompiler::DiscardVectorAndSlot() { __ Daddu(sp, sp, Operand(2 * kPointerSize)); } +void PropertyHandlerCompiler::PushReturnAddress(Register tmp) { + // No-op. Return address is in ra register. +} + +void PropertyHandlerCompiler::PopReturnAddress(Register tmp) { + // No-op. Return address is in ra register. +} void PropertyHandlerCompiler::GenerateDictionaryNegativeLookup( MacroAssembler* masm, Label* miss_label, Register receiver, @@ -317,24 +330,6 @@ void PropertyHandlerCompiler::GenerateApiAccessorCall( __ TailCallStub(&stub); } - -static void StoreIC_PushArgs(MacroAssembler* masm) { - __ Push(StoreDescriptor::ReceiverRegister(), StoreDescriptor::NameRegister(), - StoreDescriptor::ValueRegister(), - StoreWithVectorDescriptor::SlotRegister(), - StoreWithVectorDescriptor::VectorRegister()); -} - - -void ElementHandlerCompiler::GenerateStoreSlow(MacroAssembler* masm) { - StoreIC_PushArgs(masm); - - // The slow case calls into the runtime to complete the store without causing - // an IC miss that would otherwise cause a transition to the generic stub. - __ TailCallRuntime(Runtime::kKeyedStoreIC_Slow); -} - - #undef __ #define __ ACCESS_MASM(masm()) @@ -353,12 +348,6 @@ void NamedStoreHandlerCompiler::GenerateRestoreName(Handle<Name> name) { } -void NamedStoreHandlerCompiler::RearrangeVectorAndSlot( - Register current_map, Register destination_map) { - DCHECK(false); // Not implemented. -} - - void NamedStoreHandlerCompiler::GenerateRestoreMap(Handle<Map> transition, Register map_reg, Register scratch, @@ -615,6 +604,9 @@ void NamedLoadHandlerCompiler::GenerateLoadInterceptor(Register holder_reg) { __ TailCallRuntime(Runtime::kLoadPropertyWithInterceptor); } +void NamedStoreHandlerCompiler::ZapStackArgumentsRegisterAliases() { + STATIC_ASSERT(!StoreWithVectorDescriptor::kPassLastArgsOnStack); +} Handle<Code> NamedStoreHandlerCompiler::CompileStoreCallback( Handle<JSObject> object, Handle<Name> name, Handle<AccessorInfo> callback, @@ -675,7 +667,7 @@ Handle<Code> NamedLoadHandlerCompiler::CompileLoadGlobal( DiscardVectorAndSlot(); } __ Ret(USE_DELAY_SLOT); - __ mov(v0, result); + __ Move(v0, result); // Ensure the stub returns correct value. FrontendFooter(name, &miss); diff --git a/src/ic/mips64/ic-mips64.cc b/src/ic/mips64/ic-mips64.cc index b551bc70..c2f3cb60 100644 --- a/src/ic/mips64/ic-mips64.cc +++ b/src/ic/mips64/ic-mips64.cc @@ -496,7 +496,8 @@ static void KeyedStoreGenerateMegamorphicHelper( __ SmiScale(scratch, key, kPointerSizeLog2); __ Daddu(address, address, scratch); __ sd(value, MemOperand(address)); - __ Ret(); + __ Ret(USE_DELAY_SLOT); + __ Move(v0, value); // Ensure the stub returns correct value. __ bind(&non_smi_value); // Escape to elements kind transition case. @@ -518,7 +519,8 @@ static void KeyedStoreGenerateMegamorphicHelper( __ mov(scratch, value); // Preserve the value which is returned. __ RecordWrite(elements, address, scratch, kRAHasNotBeenSaved, kDontSaveFPRegs, EMIT_REMEMBERED_SET, OMIT_SMI_CHECK); - __ Ret(); + __ Ret(USE_DELAY_SLOT); + __ Move(v0, value); // Ensure the stub returns correct value. __ bind(fast_double); if (check_map == kCheckMap) { @@ -549,7 +551,8 @@ static void KeyedStoreGenerateMegamorphicHelper( __ Daddu(scratch, key, Operand(Smi::FromInt(1))); __ sd(scratch, FieldMemOperand(receiver, JSArray::kLengthOffset)); } - __ Ret(); + __ Ret(USE_DELAY_SLOT); + __ Move(v0, value); // Ensure the stub returns correct value. __ bind(&transition_smi_elements); // Transition the array appropriately depending on the value type. @@ -714,10 +717,11 @@ void KeyedStoreIC::GenerateMegamorphic(MacroAssembler* masm, static void StoreIC_PushArgs(MacroAssembler* masm) { - __ Push(StoreDescriptor::ReceiverRegister(), StoreDescriptor::NameRegister(), - StoreDescriptor::ValueRegister(), + __ Push(StoreWithVectorDescriptor::ValueRegister(), StoreWithVectorDescriptor::SlotRegister(), - StoreWithVectorDescriptor::VectorRegister()); + StoreWithVectorDescriptor::VectorRegister(), + StoreWithVectorDescriptor::ReceiverRegister(), + StoreWithVectorDescriptor::NameRegister()); } @@ -727,6 +731,14 @@ void KeyedStoreIC::GenerateMiss(MacroAssembler* masm) { __ TailCallRuntime(Runtime::kKeyedStoreIC_Miss); } +void KeyedStoreIC::GenerateSlow(MacroAssembler* masm) { + StoreIC_PushArgs(masm); + + // The slow case calls into the runtime to complete the store without causing + // an IC miss that would otherwise cause a transition to the generic stub. + __ TailCallRuntime(Runtime::kKeyedStoreIC_Slow); +} + void StoreIC::GenerateMiss(MacroAssembler* masm) { StoreIC_PushArgs(masm); @@ -750,7 +762,8 @@ void StoreIC::GenerateNormal(MacroAssembler* masm) { GenerateDictionaryStore(masm, &miss, dictionary, name, value, a6, a7); Counters* counters = masm->isolate()->counters(); __ IncrementCounter(counters->ic_store_normal_hit(), 1, a6, a7); - __ Ret(); + __ Ret(USE_DELAY_SLOT); + __ Move(v0, value); // Ensure the stub returns correct value. __ bind(&miss); __ IncrementCounter(counters->ic_store_normal_miss(), 1, a6, a7); diff --git a/src/ic/ppc/handler-compiler-ppc.cc b/src/ic/ppc/handler-compiler-ppc.cc index 22c0608c..aafdc77c 100644 --- a/src/ic/ppc/handler-compiler-ppc.cc +++ b/src/ic/ppc/handler-compiler-ppc.cc @@ -108,13 +108,19 @@ void NamedStoreHandlerCompiler::GenerateStoreViaSetter( void PropertyHandlerCompiler::PushVectorAndSlot(Register vector, Register slot) { MacroAssembler* masm = this->masm(); - __ Push(vector, slot); + STATIC_ASSERT(LoadWithVectorDescriptor::kSlot < + LoadWithVectorDescriptor::kVector); + STATIC_ASSERT(StoreWithVectorDescriptor::kSlot < + StoreWithVectorDescriptor::kVector); + STATIC_ASSERT(StoreTransitionDescriptor::kSlot < + StoreTransitionDescriptor::kVector); + __ Push(slot, vector); } void PropertyHandlerCompiler::PopVectorAndSlot(Register vector, Register slot) { MacroAssembler* masm = this->masm(); - __ Pop(vector, slot); + __ Pop(slot, vector); } @@ -124,6 +130,13 @@ void PropertyHandlerCompiler::DiscardVectorAndSlot() { __ addi(sp, sp, Operand(2 * kPointerSize)); } +void PropertyHandlerCompiler::PushReturnAddress(Register tmp) { + // No-op. Return address is in lr register. +} + +void PropertyHandlerCompiler::PopReturnAddress(Register tmp) { + // No-op. Return address is in lr register. +} void PropertyHandlerCompiler::GenerateDictionaryNegativeLookup( MacroAssembler* masm, Label* miss_label, Register receiver, @@ -325,24 +338,6 @@ void PropertyHandlerCompiler::GenerateApiAccessorCall( __ TailCallStub(&stub); } - -static void StoreIC_PushArgs(MacroAssembler* masm) { - __ Push(StoreDescriptor::ReceiverRegister(), StoreDescriptor::NameRegister(), - StoreDescriptor::ValueRegister(), - StoreWithVectorDescriptor::SlotRegister(), - StoreWithVectorDescriptor::VectorRegister()); -} - - -void ElementHandlerCompiler::GenerateStoreSlow(MacroAssembler* masm) { - StoreIC_PushArgs(masm); - - // The slow case calls into the runtime to complete the store without causing - // an IC miss that would otherwise cause a transition to the generic stub. - __ TailCallRuntime(Runtime::kKeyedStoreIC_Slow); -} - - #undef __ #define __ ACCESS_MASM(masm()) @@ -361,12 +356,6 @@ void NamedStoreHandlerCompiler::GenerateRestoreName(Handle<Name> name) { } -void NamedStoreHandlerCompiler::RearrangeVectorAndSlot( - Register current_map, Register destination_map) { - DCHECK(false); // Not implemented. -} - - void NamedStoreHandlerCompiler::GenerateRestoreMap(Handle<Map> transition, Register map_reg, Register scratch, @@ -624,6 +613,9 @@ void NamedLoadHandlerCompiler::GenerateLoadInterceptor(Register holder_reg) { __ TailCallRuntime(Runtime::kLoadPropertyWithInterceptor); } +void NamedStoreHandlerCompiler::ZapStackArgumentsRegisterAliases() { + STATIC_ASSERT(!StoreWithVectorDescriptor::kPassLastArgsOnStack); +} Handle<Code> NamedStoreHandlerCompiler::CompileStoreCallback( Handle<JSObject> object, Handle<Name> name, Handle<AccessorInfo> callback, diff --git a/src/ic/ppc/ic-ppc.cc b/src/ic/ppc/ic-ppc.cc index fd2962d0..6dd78814 100644 --- a/src/ic/ppc/ic-ppc.cc +++ b/src/ic/ppc/ic-ppc.cc @@ -451,10 +451,11 @@ void KeyedLoadIC::GenerateMegamorphic(MacroAssembler* masm) { static void StoreIC_PushArgs(MacroAssembler* masm) { - __ Push(StoreDescriptor::ReceiverRegister(), StoreDescriptor::NameRegister(), - StoreDescriptor::ValueRegister(), + __ Push(StoreWithVectorDescriptor::ValueRegister(), StoreWithVectorDescriptor::SlotRegister(), - StoreWithVectorDescriptor::VectorRegister()); + StoreWithVectorDescriptor::VectorRegister(), + StoreWithVectorDescriptor::ReceiverRegister(), + StoreWithVectorDescriptor::NameRegister()); } @@ -464,6 +465,13 @@ void KeyedStoreIC::GenerateMiss(MacroAssembler* masm) { __ TailCallRuntime(Runtime::kKeyedStoreIC_Miss); } +void KeyedStoreIC::GenerateSlow(MacroAssembler* masm) { + StoreIC_PushArgs(masm); + + // The slow case calls into the runtime to complete the store without causing + // an IC miss that would otherwise cause a transition to the generic stub. + __ TailCallRuntime(Runtime::kKeyedStoreIC_Slow); +} static void KeyedStoreGenerateMegamorphicHelper( MacroAssembler* masm, Label* fast_object, Label* fast_double, Label* slow, diff --git a/src/ic/s390/handler-compiler-s390.cc b/src/ic/s390/handler-compiler-s390.cc index b399c5a6..504baceb 100644 --- a/src/ic/s390/handler-compiler-s390.cc +++ b/src/ic/s390/handler-compiler-s390.cc @@ -105,12 +105,18 @@ void NamedStoreHandlerCompiler::GenerateStoreViaSetter( void PropertyHandlerCompiler::PushVectorAndSlot(Register vector, Register slot) { MacroAssembler* masm = this->masm(); - __ Push(vector, slot); + STATIC_ASSERT(LoadWithVectorDescriptor::kSlot < + LoadWithVectorDescriptor::kVector); + STATIC_ASSERT(StoreWithVectorDescriptor::kSlot < + StoreWithVectorDescriptor::kVector); + STATIC_ASSERT(StoreTransitionDescriptor::kSlot < + StoreTransitionDescriptor::kVector); + __ Push(slot, vector); } void PropertyHandlerCompiler::PopVectorAndSlot(Register vector, Register slot) { MacroAssembler* masm = this->masm(); - __ Pop(vector, slot); + __ Pop(slot, vector); } void PropertyHandlerCompiler::DiscardVectorAndSlot() { @@ -119,6 +125,14 @@ void PropertyHandlerCompiler::DiscardVectorAndSlot() { __ la(sp, MemOperand(sp, 2 * kPointerSize)); } +void PropertyHandlerCompiler::PushReturnAddress(Register tmp) { + // No-op. Return address is in lr register. +} + +void PropertyHandlerCompiler::PopReturnAddress(Register tmp) { + // No-op. Return address is in lr register. +} + void PropertyHandlerCompiler::GenerateDictionaryNegativeLookup( MacroAssembler* masm, Label* miss_label, Register receiver, Handle<Name> name, Register scratch0, Register scratch1) { @@ -310,21 +324,6 @@ void PropertyHandlerCompiler::GenerateApiAccessorCall( __ TailCallStub(&stub); } -static void StoreIC_PushArgs(MacroAssembler* masm) { - __ Push(StoreDescriptor::ReceiverRegister(), StoreDescriptor::NameRegister(), - StoreDescriptor::ValueRegister(), - StoreWithVectorDescriptor::SlotRegister(), - StoreWithVectorDescriptor::VectorRegister()); -} - -void ElementHandlerCompiler::GenerateStoreSlow(MacroAssembler* masm) { - StoreIC_PushArgs(masm); - - // The slow case calls into the runtime to complete the store without causing - // an IC miss that would otherwise cause a transition to the generic stub. - __ TailCallRuntime(Runtime::kKeyedStoreIC_Slow); -} - #undef __ #define __ ACCESS_MASM(masm()) @@ -340,11 +339,6 @@ void NamedStoreHandlerCompiler::GenerateRestoreName(Handle<Name> name) { __ mov(this->name(), Operand(name)); } -void NamedStoreHandlerCompiler::RearrangeVectorAndSlot( - Register current_map, Register destination_map) { - DCHECK(false); // Not implemented. -} - void NamedStoreHandlerCompiler::GenerateRestoreMap(Handle<Map> transition, Register map_reg, Register scratch, @@ -593,6 +587,10 @@ void NamedLoadHandlerCompiler::GenerateLoadInterceptor(Register holder_reg) { __ TailCallRuntime(Runtime::kLoadPropertyWithInterceptor); } +void NamedStoreHandlerCompiler::ZapStackArgumentsRegisterAliases() { + STATIC_ASSERT(!StoreWithVectorDescriptor::kPassLastArgsOnStack); +} + Handle<Code> NamedStoreHandlerCompiler::CompileStoreCallback( Handle<JSObject> object, Handle<Name> name, Handle<AccessorInfo> callback, LanguageMode language_mode) { diff --git a/src/ic/s390/ic-s390.cc b/src/ic/s390/ic-s390.cc index 6bb484a2..08eb3e4f 100644 --- a/src/ic/s390/ic-s390.cc +++ b/src/ic/s390/ic-s390.cc @@ -437,10 +437,11 @@ void KeyedLoadIC::GenerateMegamorphic(MacroAssembler* masm) { } static void StoreIC_PushArgs(MacroAssembler* masm) { - __ Push(StoreDescriptor::ReceiverRegister(), StoreDescriptor::NameRegister(), - StoreDescriptor::ValueRegister(), + __ Push(StoreWithVectorDescriptor::ValueRegister(), StoreWithVectorDescriptor::SlotRegister(), - StoreWithVectorDescriptor::VectorRegister()); + StoreWithVectorDescriptor::VectorRegister(), + StoreWithVectorDescriptor::ReceiverRegister(), + StoreWithVectorDescriptor::NameRegister()); } void KeyedStoreIC::GenerateMiss(MacroAssembler* masm) { @@ -449,6 +450,14 @@ void KeyedStoreIC::GenerateMiss(MacroAssembler* masm) { __ TailCallRuntime(Runtime::kKeyedStoreIC_Miss); } +void KeyedStoreIC::GenerateSlow(MacroAssembler* masm) { + StoreIC_PushArgs(masm); + + // The slow case calls into the runtime to complete the store without causing + // an IC miss that would otherwise cause a transition to the generic stub. + __ TailCallRuntime(Runtime::kKeyedStoreIC_Slow); +} + static void KeyedStoreGenerateMegamorphicHelper( MacroAssembler* masm, Label* fast_object, Label* fast_double, Label* slow, KeyedStoreCheckMap check_map, KeyedStoreIncrementLength increment_length, diff --git a/src/ic/stub-cache.cc b/src/ic/stub-cache.cc index 31d7e2e0..fe1adaaa 100644 --- a/src/ic/stub-cache.cc +++ b/src/ic/stub-cache.cc @@ -4,6 +4,7 @@ #include "src/ic/stub-cache.h" +#include "src/ast/ast.h" #include "src/base/bits.h" #include "src/type-info.h" diff --git a/src/ic/stub-cache.h b/src/ic/stub-cache.h index a053555d..ebcff448 100644 --- a/src/ic/stub-cache.h +++ b/src/ic/stub-cache.h @@ -10,6 +10,7 @@ namespace v8 { namespace internal { +class SmallMapList; // The stub cache is used for megamorphic property accesses. // It maps (map, name, type) to property access handlers. The cache does not diff --git a/src/ic/x64/handler-compiler-x64.cc b/src/ic/x64/handler-compiler-x64.cc index ba4daed3..f386fc5b 100644 --- a/src/ic/x64/handler-compiler-x64.cc +++ b/src/ic/x64/handler-compiler-x64.cc @@ -20,15 +20,21 @@ namespace internal { void PropertyHandlerCompiler::PushVectorAndSlot(Register vector, Register slot) { MacroAssembler* masm = this->masm(); - __ Push(vector); + STATIC_ASSERT(LoadWithVectorDescriptor::kSlot < + LoadWithVectorDescriptor::kVector); + STATIC_ASSERT(StoreWithVectorDescriptor::kSlot < + StoreWithVectorDescriptor::kVector); + STATIC_ASSERT(StoreTransitionDescriptor::kSlot < + StoreTransitionDescriptor::kVector); __ Push(slot); + __ Push(vector); } void PropertyHandlerCompiler::PopVectorAndSlot(Register vector, Register slot) { MacroAssembler* masm = this->masm(); - __ Pop(slot); __ Pop(vector); + __ Pop(slot); } @@ -38,6 +44,15 @@ void PropertyHandlerCompiler::DiscardVectorAndSlot() { __ addp(rsp, Immediate(2 * kPointerSize)); } +void PropertyHandlerCompiler::PushReturnAddress(Register tmp) { + MacroAssembler* masm = this->masm(); + __ Push(tmp); +} + +void PropertyHandlerCompiler::PopReturnAddress(Register tmp) { + MacroAssembler* masm = this->masm(); + __ Pop(tmp); +} void PropertyHandlerCompiler::GenerateDictionaryNegativeLookup( MacroAssembler* masm, Label* miss_label, Register receiver, @@ -321,34 +336,6 @@ void NamedLoadHandlerCompiler::GenerateLoadViaGetter( __ ret(0); } - -static void StoreIC_PushArgs(MacroAssembler* masm) { - Register receiver = StoreDescriptor::ReceiverRegister(); - Register name = StoreDescriptor::NameRegister(); - Register value = StoreDescriptor::ValueRegister(); - - Register slot = StoreWithVectorDescriptor::SlotRegister(); - Register vector = StoreWithVectorDescriptor::VectorRegister(); - - __ PopReturnAddressTo(r11); - __ Push(receiver); - __ Push(name); - __ Push(value); - __ Push(slot); - __ Push(vector); - __ PushReturnAddressFrom(r11); -} - - -void ElementHandlerCompiler::GenerateStoreSlow(MacroAssembler* masm) { - // Return address is on the stack. - StoreIC_PushArgs(masm); - - // Do tail-call to runtime routine. - __ TailCallRuntime(Runtime::kKeyedStoreIC_Slow); -} - - #undef __ #define __ ACCESS_MASM((masm())) @@ -367,12 +354,6 @@ void NamedStoreHandlerCompiler::GenerateRestoreName(Handle<Name> name) { } -void NamedStoreHandlerCompiler::RearrangeVectorAndSlot( - Register current_map, Register destination_map) { - DCHECK(false); // Not implemented. -} - - void NamedStoreHandlerCompiler::GenerateRestoreMap(Handle<Map> transition, Register map_reg, Register scratch, @@ -638,6 +619,9 @@ void NamedLoadHandlerCompiler::GenerateLoadInterceptor(Register holder_reg) { __ TailCallRuntime(Runtime::kLoadPropertyWithInterceptor); } +void NamedStoreHandlerCompiler::ZapStackArgumentsRegisterAliases() { + STATIC_ASSERT(!StoreWithVectorDescriptor::kPassLastArgsOnStack); +} Handle<Code> NamedStoreHandlerCompiler::CompileStoreCallback( Handle<JSObject> object, Handle<Name> name, Handle<AccessorInfo> callback, diff --git a/src/ic/x64/ic-x64.cc b/src/ic/x64/ic-x64.cc index 21a11483..d0445a22 100644 --- a/src/ic/x64/ic-x64.cc +++ b/src/ic/x64/ic-x64.cc @@ -706,21 +706,20 @@ void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) { } static void StoreIC_PushArgs(MacroAssembler* masm) { - Register receiver = StoreDescriptor::ReceiverRegister(); - Register name = StoreDescriptor::NameRegister(); - Register value = StoreDescriptor::ValueRegister(); + Register receiver = StoreWithVectorDescriptor::ReceiverRegister(); + Register name = StoreWithVectorDescriptor::NameRegister(); + Register value = StoreWithVectorDescriptor::ValueRegister(); + Register slot = StoreWithVectorDescriptor::SlotRegister(); + Register vector = StoreWithVectorDescriptor::VectorRegister(); Register temp = r11; - DCHECK(!temp.is(receiver) && !temp.is(name) && !temp.is(value)); + DCHECK(!AreAliased(receiver, name, value, slot, vector, temp)); __ PopReturnAddressTo(temp); - __ Push(receiver); - __ Push(name); __ Push(value); - Register slot = StoreWithVectorDescriptor::SlotRegister(); - Register vector = StoreWithVectorDescriptor::VectorRegister(); - DCHECK(!temp.is(slot) && !temp.is(vector)); __ Push(slot); __ Push(vector); + __ Push(receiver); + __ Push(name); __ PushReturnAddressFrom(temp); } @@ -764,6 +763,13 @@ void KeyedStoreIC::GenerateMiss(MacroAssembler* masm) { __ TailCallRuntime(Runtime::kKeyedStoreIC_Miss); } +void KeyedStoreIC::GenerateSlow(MacroAssembler* masm) { + // Return address is on the stack. + StoreIC_PushArgs(masm); + + // Do tail-call to runtime routine. + __ TailCallRuntime(Runtime::kKeyedStoreIC_Slow); +} #undef __ diff --git a/src/ic/x87/handler-compiler-x87.cc b/src/ic/x87/handler-compiler-x87.cc index 4bf0af25..5eca3dc0 100644 --- a/src/ic/x87/handler-compiler-x87.cc +++ b/src/ic/x87/handler-compiler-x87.cc @@ -59,15 +59,21 @@ void NamedLoadHandlerCompiler::GenerateLoadViaGetter( void PropertyHandlerCompiler::PushVectorAndSlot(Register vector, Register slot) { MacroAssembler* masm = this->masm(); - __ push(vector); + STATIC_ASSERT(LoadWithVectorDescriptor::kSlot < + LoadWithVectorDescriptor::kVector); + STATIC_ASSERT(StoreWithVectorDescriptor::kSlot < + StoreWithVectorDescriptor::kVector); + STATIC_ASSERT(StoreTransitionDescriptor::kSlot < + StoreTransitionDescriptor::kVector); __ push(slot); + __ push(vector); } void PropertyHandlerCompiler::PopVectorAndSlot(Register vector, Register slot) { MacroAssembler* masm = this->masm(); - __ pop(slot); __ pop(vector); + __ pop(slot); } @@ -77,6 +83,15 @@ void PropertyHandlerCompiler::DiscardVectorAndSlot() { __ add(esp, Immediate(2 * kPointerSize)); } +void PropertyHandlerCompiler::PushReturnAddress(Register tmp) { + MacroAssembler* masm = this->masm(); + __ push(tmp); +} + +void PropertyHandlerCompiler::PopReturnAddress(Register tmp) { + MacroAssembler* masm = this->masm(); + __ pop(tmp); +} void PropertyHandlerCompiler::GenerateDictionaryNegativeLookup( MacroAssembler* masm, Label* miss_label, Register receiver, @@ -150,12 +165,16 @@ void PropertyHandlerCompiler::GenerateApiAccessorCall( DCHECK(!accessor_holder.is(scratch)); // Copy return value. __ pop(scratch); - // receiver + + if (is_store) { + // Discard stack arguments. + __ add(esp, Immediate(StoreWithVectorDescriptor::kStackArgumentsCount * + kPointerSize)); + } + // Write the receiver and arguments to stack frame. __ push(receiver); - // Write the arguments to stack frame. if (is_store) { - DCHECK(!receiver.is(store_parameter)); - DCHECK(!scratch.is(store_parameter)); + DCHECK(!AreAliased(receiver, scratch, store_parameter)); __ push(store_parameter); } __ push(scratch); @@ -252,8 +271,13 @@ void NamedStoreHandlerCompiler::GenerateStoreViaSetter( MacroAssembler* masm, Handle<Map> map, Register receiver, Register holder, int accessor_index, int expected_arguments, Register scratch) { // ----------- S t a t e ------------- - // -- esp[0] : return address + // -- esp[12] : value + // -- esp[8] : slot + // -- esp[4] : vector + // -- esp[0] : return address // ----------------------------------- + __ LoadParameterFromStack<Descriptor>(value(), Descriptor::kValue); + { FrameScope scope(masm, StackFrame::INTERNAL); @@ -290,7 +314,14 @@ void NamedStoreHandlerCompiler::GenerateStoreViaSetter( // Restore context register. __ pop(esi); } - __ ret(0); + if (accessor_index >= 0) { + __ ret(StoreWithVectorDescriptor::kStackArgumentsCount * kPointerSize); + } else { + // If we generate a global code snippet for deoptimization only, don't try + // to drop stack arguments for the StoreIC because they are not a part of + // expression stack and deoptimizer does not reconstruct them. + __ ret(0); + } } @@ -316,32 +347,6 @@ static void CompileCallLoadPropertyWithInterceptor( __ CallRuntime(id); } - -static void StoreIC_PushArgs(MacroAssembler* masm) { - Register receiver = StoreDescriptor::ReceiverRegister(); - Register name = StoreDescriptor::NameRegister(); - Register value = StoreDescriptor::ValueRegister(); - Register slot = StoreWithVectorDescriptor::SlotRegister(); - Register vector = StoreWithVectorDescriptor::VectorRegister(); - - __ xchg(receiver, Operand(esp, 0)); - __ push(name); - __ push(value); - __ push(slot); - __ push(vector); - __ push(receiver); // which contains the return address. -} - - -void ElementHandlerCompiler::GenerateStoreSlow(MacroAssembler* masm) { - // Return address is on the stack. - StoreIC_PushArgs(masm); - - // Do tail-call to runtime routine. - __ TailCallRuntime(Runtime::kKeyedStoreIC_Slow); -} - - #undef __ #define __ ACCESS_MASM(masm()) @@ -360,19 +365,6 @@ void NamedStoreHandlerCompiler::GenerateRestoreName(Handle<Name> name) { } -void NamedStoreHandlerCompiler::RearrangeVectorAndSlot( - Register current_map, Register destination_map) { - DCHECK(destination_map.is(StoreTransitionHelper::MapRegister())); - DCHECK(current_map.is(StoreTransitionHelper::VectorRegister())); - ExternalReference virtual_slot = - ExternalReference::virtual_slot_register(isolate()); - __ mov(destination_map, current_map); - __ pop(current_map); - __ mov(Operand::StaticVariable(virtual_slot), current_map); - __ pop(current_map); // put vector in place. -} - - void NamedStoreHandlerCompiler::GenerateRestoreMap(Handle<Map> transition, Register map_reg, Register scratch, @@ -532,7 +524,7 @@ void NamedLoadHandlerCompiler::FrontendFooter(Handle<Name> name, Label* miss) { Label success; __ jmp(&success); __ bind(miss); - if (IC::ICUseVector(kind())) { + if (IC::ShouldPushPopSlotAndVector(kind())) { DCHECK(kind() == Code::LOAD_IC); PopVectorAndSlot(); } @@ -547,7 +539,7 @@ void NamedStoreHandlerCompiler::FrontendFooter(Handle<Name> name, Label* miss) { Label success; __ jmp(&success); GenerateRestoreName(miss, name); - if (IC::ICUseVector(kind())) PopVectorAndSlot(); + DCHECK(!IC::ShouldPushPopSlotAndVector(kind())); TailCallBuiltin(masm(), MissBuiltin(kind())); __ bind(&success); } @@ -641,13 +633,26 @@ void NamedLoadHandlerCompiler::GenerateLoadInterceptor(Register holder_reg) { __ TailCallRuntime(Runtime::kLoadPropertyWithInterceptor); } +void NamedStoreHandlerCompiler::ZapStackArgumentsRegisterAliases() { + // Zap register aliases of the arguments passed on the stack to ensure they + // are properly loaded by the handler (debug-only). + STATIC_ASSERT(Descriptor::kPassLastArgsOnStack); + STATIC_ASSERT(Descriptor::kStackArgumentsCount == 3); + __ mov(Descriptor::ValueRegister(), Immediate(kDebugZapValue)); + __ mov(Descriptor::SlotRegister(), Immediate(kDebugZapValue)); + __ mov(Descriptor::VectorRegister(), Immediate(kDebugZapValue)); +} Handle<Code> NamedStoreHandlerCompiler::CompileStoreCallback( Handle<JSObject> object, Handle<Name> name, Handle<AccessorInfo> callback, LanguageMode language_mode) { Register holder_reg = Frontend(name); + __ LoadParameterFromStack<Descriptor>(value(), Descriptor::kValue); __ pop(scratch1()); // remove the return address + // Discard stack arguments. + __ add(esp, Immediate(StoreWithVectorDescriptor::kStackArgumentsCount * + kPointerSize)); __ push(receiver()); __ push(holder_reg); // If the callback cannot leak, then push the callback directly, @@ -679,7 +684,7 @@ Register NamedStoreHandlerCompiler::value() { Handle<Code> NamedLoadHandlerCompiler::CompileLoadGlobal( Handle<PropertyCell> cell, Handle<Name> name, bool is_configurable) { Label miss; - if (IC::ICUseVector(kind())) { + if (IC::ShouldPushPopSlotAndVector(kind())) { PushVectorAndSlot(); } FrontendHeader(receiver(), name, &miss, DONT_RETURN_ANYTHING); @@ -701,7 +706,7 @@ Handle<Code> NamedLoadHandlerCompiler::CompileLoadGlobal( Counters* counters = isolate()->counters(); __ IncrementCounter(counters->ic_named_load_global_stub(), 1); // The code above already loads the result into the return register. - if (IC::ICUseVector(kind())) { + if (IC::ShouldPushPopSlotAndVector(kind())) { DiscardVectorAndSlot(); } __ ret(0); diff --git a/src/ic/x87/ic-compiler-x87.cc b/src/ic/x87/ic-compiler-x87.cc index 9edf63b7..11a8cdcd 100644 --- a/src/ic/x87/ic-compiler-x87.cc +++ b/src/ic/x87/ic-compiler-x87.cc @@ -15,14 +15,21 @@ namespace internal { void PropertyICCompiler::GenerateRuntimeSetProperty( MacroAssembler* masm, LanguageMode language_mode) { - // Return address is on the stack. - DCHECK(!ebx.is(StoreDescriptor::ReceiverRegister()) && - !ebx.is(StoreDescriptor::NameRegister()) && - !ebx.is(StoreDescriptor::ValueRegister())); + typedef StoreWithVectorDescriptor Descriptor; + STATIC_ASSERT(Descriptor::kStackArgumentsCount == 3); + // ----------- S t a t e ------------- + // -- esp[12] : value + // -- esp[8] : slot + // -- esp[4] : vector + // -- esp[0] : return address + // ----------------------------------- + __ LoadParameterFromStack<Descriptor>(Descriptor::ValueRegister(), + Descriptor::kValue); + + __ mov(Operand(esp, 12), Descriptor::ReceiverRegister()); + __ mov(Operand(esp, 8), Descriptor::NameRegister()); + __ mov(Operand(esp, 4), Descriptor::ValueRegister()); __ pop(ebx); - __ push(StoreDescriptor::ReceiverRegister()); - __ push(StoreDescriptor::NameRegister()); - __ push(StoreDescriptor::ValueRegister()); __ push(Immediate(Smi::FromInt(language_mode))); __ push(ebx); // return address diff --git a/src/ic/x87/ic-x87.cc b/src/ic/x87/ic-x87.cc index 76933f01..baf435e0 100644 --- a/src/ic/x87/ic-x87.cc +++ b/src/ic/x87/ic-x87.cc @@ -409,7 +409,7 @@ static void KeyedStoreGenerateMegamorphicHelper( } // It's irrelevant whether array is smi-only or not when writing a smi. __ mov(FixedArrayElementOperand(ebx, key), value); - __ ret(0); + __ ret(StoreWithVectorDescriptor::kStackArgumentsCount * kPointerSize); __ bind(&non_smi_value); // Escape to elements kind transition case. @@ -428,7 +428,7 @@ static void KeyedStoreGenerateMegamorphicHelper( __ mov(edx, value); // Preserve the value which is returned. __ RecordWriteArray(ebx, edx, key, kDontSaveFPRegs, EMIT_REMEMBERED_SET, OMIT_SMI_CHECK); - __ ret(0); + __ ret(StoreWithVectorDescriptor::kStackArgumentsCount * kPointerSize); __ bind(fast_double); if (check_map == kCheckMap) { @@ -457,7 +457,7 @@ static void KeyedStoreGenerateMegamorphicHelper( __ add(FieldOperand(receiver, JSArray::kLengthOffset), Immediate(Smi::FromInt(1))); } - __ ret(0); + __ ret(StoreWithVectorDescriptor::kStackArgumentsCount * kPointerSize); __ bind(&transition_smi_elements); __ mov(ebx, FieldOperand(receiver, HeapObject::kMapOffset)); @@ -504,12 +504,13 @@ static void KeyedStoreGenerateMegamorphicHelper( void KeyedStoreIC::GenerateMegamorphic(MacroAssembler* masm, LanguageMode language_mode) { + typedef StoreWithVectorDescriptor Descriptor; // Return address is on the stack. Label slow, fast_object, fast_object_grow; Label fast_double, fast_double_grow; Label array, extra, check_if_double_array, maybe_name_key, miss; - Register receiver = StoreDescriptor::ReceiverRegister(); - Register key = StoreDescriptor::NameRegister(); + Register receiver = Descriptor::ReceiverRegister(); + Register key = Descriptor::NameRegister(); DCHECK(receiver.is(edx)); DCHECK(key.is(ecx)); @@ -522,6 +523,10 @@ void KeyedStoreIC::GenerateMegamorphic(MacroAssembler* masm, __ test_b(FieldOperand(edi, Map::kBitFieldOffset), Immediate(1 << Map::kIsAccessCheckNeeded)); __ j(not_zero, &slow); + + __ LoadParameterFromStack<Descriptor>(Descriptor::ValueRegister(), + Descriptor::kValue); + // Check that the key is a smi. __ JumpIfNotSmi(key, &maybe_name_key); __ CmpInstanceType(edi, JS_ARRAY_TYPE); @@ -551,22 +556,9 @@ void KeyedStoreIC::GenerateMegamorphic(MacroAssembler* masm, __ movzx_b(ebx, FieldOperand(ebx, Map::kInstanceTypeOffset)); __ JumpIfNotUniqueNameInstanceType(ebx, &slow); - - // The handlers in the stub cache expect a vector and slot. Since we won't - // change the IC from any downstream misses, a dummy vector can be used. - Handle<TypeFeedbackVector> dummy_vector = - TypeFeedbackVector::DummyVector(masm->isolate()); - int slot = dummy_vector->GetIndex( - FeedbackVectorSlot(TypeFeedbackVector::kDummyKeyedStoreICSlot)); - __ push(Immediate(Smi::FromInt(slot))); - __ push(Immediate(dummy_vector)); - masm->isolate()->store_stub_cache()->GenerateProbe(masm, receiver, key, edi, no_reg); - __ pop(StoreWithVectorDescriptor::VectorRegister()); - __ pop(StoreWithVectorDescriptor::SlotRegister()); - // Cache miss. __ jmp(&miss); @@ -705,18 +697,21 @@ void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) { } static void StoreIC_PushArgs(MacroAssembler* masm) { - Register receiver = StoreDescriptor::ReceiverRegister(); - Register name = StoreDescriptor::NameRegister(); - Register value = StoreDescriptor::ValueRegister(); - Register slot = StoreWithVectorDescriptor::SlotRegister(); - Register vector = StoreWithVectorDescriptor::VectorRegister(); - - __ xchg(receiver, Operand(esp, 0)); + Register receiver = StoreWithVectorDescriptor::ReceiverRegister(); + Register name = StoreWithVectorDescriptor::NameRegister(); + + STATIC_ASSERT(StoreWithVectorDescriptor::kStackArgumentsCount == 3); + // Current stack layout: + // - esp[12] -- value + // - esp[8] -- slot + // - esp[4] -- vector + // - esp[0] -- return address + + Register return_address = StoreWithVectorDescriptor::SlotRegister(); + __ pop(return_address); + __ push(receiver); __ push(name); - __ push(value); - __ push(slot); - __ push(vector); - __ push(receiver); // Contains the return address. + __ push(return_address); } @@ -730,32 +725,33 @@ void StoreIC::GenerateMiss(MacroAssembler* masm) { void StoreIC::GenerateNormal(MacroAssembler* masm) { + typedef StoreWithVectorDescriptor Descriptor; Label restore_miss; - Register receiver = StoreDescriptor::ReceiverRegister(); - Register name = StoreDescriptor::NameRegister(); - Register value = StoreDescriptor::ValueRegister(); - Register vector = StoreWithVectorDescriptor::VectorRegister(); - Register slot = StoreWithVectorDescriptor::SlotRegister(); - - // A lot of registers are needed for storing to slow case - // objects. Push and restore receiver but rely on - // GenerateDictionaryStore preserving the value and name. + Register receiver = Descriptor::ReceiverRegister(); + Register name = Descriptor::NameRegister(); + Register value = Descriptor::ValueRegister(); + // Since the slot and vector values are passed on the stack we can use + // respective registers as scratch registers. + Register scratch1 = Descriptor::VectorRegister(); + Register scratch2 = Descriptor::SlotRegister(); + + __ LoadParameterFromStack<Descriptor>(value, Descriptor::kValue); + + // A lot of registers are needed for storing to slow case objects. + // Push and restore receiver but rely on GenerateDictionaryStore preserving + // the value and name. __ push(receiver); - __ push(vector); - __ push(slot); - Register dictionary = ebx; + Register dictionary = receiver; __ mov(dictionary, FieldOperand(receiver, JSObject::kPropertiesOffset)); GenerateDictionaryStore(masm, &restore_miss, dictionary, name, value, - receiver, edi); - __ Drop(3); + scratch1, scratch2); + __ Drop(1); Counters* counters = masm->isolate()->counters(); __ IncrementCounter(counters->ic_store_normal_hit(), 1); - __ ret(0); + __ ret(Descriptor::kStackArgumentsCount * kPointerSize); __ bind(&restore_miss); - __ pop(slot); - __ pop(vector); __ pop(receiver); __ IncrementCounter(counters->ic_store_normal_miss(), 1); GenerateMiss(masm); @@ -770,6 +766,13 @@ void KeyedStoreIC::GenerateMiss(MacroAssembler* masm) { __ TailCallRuntime(Runtime::kKeyedStoreIC_Miss); } +void KeyedStoreIC::GenerateSlow(MacroAssembler* masm) { + // Return address is on the stack. + StoreIC_PushArgs(masm); + + // Do tail-call to runtime routine. + __ TailCallRuntime(Runtime::kKeyedStoreIC_Slow); +} #undef __ diff --git a/src/ic/x87/stub-cache-x87.cc b/src/ic/x87/stub-cache-x87.cc index e0656f7c..68fa6154 100644 --- a/src/ic/x87/stub-cache-x87.cc +++ b/src/ic/x87/stub-cache-x87.cc @@ -22,8 +22,6 @@ static void ProbeTable(StubCache* stub_cache, MacroAssembler* masm, ExternalReference key_offset(stub_cache->key_reference(table)); ExternalReference value_offset(stub_cache->value_reference(table)); ExternalReference map_offset(stub_cache->map_reference(table)); - ExternalReference virtual_register = - ExternalReference::virtual_handler_register(masm->isolate()); Label miss; Code::Kind ic_kind = stub_cache->ic_kind(); @@ -55,19 +53,15 @@ static void ProbeTable(StubCache* stub_cache, MacroAssembler* masm, } #endif - // The vector and slot were pushed onto the stack before starting the - // probe, and need to be dropped before calling the handler. if (is_vector_store) { - // The overlap here is rather embarrassing. One does what one must. - Register vector = StoreWithVectorDescriptor::VectorRegister(); + // The value, vector and slot were passed to the IC on the stack and + // they are still there. So we can just jump to the handler. DCHECK(extra.is(StoreWithVectorDescriptor::SlotRegister())); __ add(extra, Immediate(Code::kHeaderSize - kHeapObjectTag)); - __ pop(vector); - __ mov(Operand::StaticVariable(virtual_register), extra); - __ pop(extra); // Pop "slot". - // Jump to the first instruction in the code stub. - __ jmp(Operand::StaticVariable(virtual_register)); + __ jmp(extra); } else { + // The vector and slot were pushed onto the stack before starting the + // probe, and need to be dropped before calling the handler. __ pop(LoadWithVectorDescriptor::VectorRegister()); __ pop(LoadDescriptor::SlotRegister()); __ add(extra, Immediate(Code::kHeaderSize - kHeapObjectTag)); @@ -110,19 +104,10 @@ static void ProbeTable(StubCache* stub_cache, MacroAssembler* masm, // Jump to the first instruction in the code stub. if (is_vector_store) { - // The vector and slot were pushed onto the stack before starting the - // probe, and need to be dropped before calling the handler. - Register vector = StoreWithVectorDescriptor::VectorRegister(); DCHECK(offset.is(StoreWithVectorDescriptor::SlotRegister())); - __ add(offset, Immediate(Code::kHeaderSize - kHeapObjectTag)); - __ mov(Operand::StaticVariable(virtual_register), offset); - __ pop(vector); - __ pop(offset); // Pop "slot". - __ jmp(Operand::StaticVariable(virtual_register)); - } else { - __ add(offset, Immediate(Code::kHeaderSize - kHeapObjectTag)); - __ jmp(offset); } + __ add(offset, Immediate(Code::kHeaderSize - kHeapObjectTag)); + __ jmp(offset); // Pop at miss. __ bind(&miss); |