diff options
Diffstat (limited to 'src/ic/x87')
-rw-r--r-- | src/ic/x87/handler-compiler-x87.cc | 107 | ||||
-rw-r--r-- | src/ic/x87/ic-compiler-x87.cc | 21 | ||||
-rw-r--r-- | src/ic/x87/ic-x87.cc | 95 | ||||
-rw-r--r-- | src/ic/x87/stub-cache-x87.cc | 29 |
4 files changed, 126 insertions, 126 deletions
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); |