| Index: src/ic/x64/handler-compiler-x64.cc
|
| diff --git a/src/ic/x64/ic-compiler-x64.cc b/src/ic/x64/handler-compiler-x64.cc
|
| similarity index 88%
|
| copy from src/ic/x64/ic-compiler-x64.cc
|
| copy to src/ic/x64/handler-compiler-x64.cc
|
| index 793bd0efb5dc2fd241579cfcf447d1f8fb9429c8..0117a96978aa9eebd72470fe1b6593e2d04a1b64 100644
|
| --- a/src/ic/x64/ic-compiler-x64.cc
|
| +++ b/src/ic/x64/handler-compiler-x64.cc
|
| @@ -7,14 +7,13 @@
|
| #if V8_TARGET_ARCH_X64
|
|
|
| #include "src/ic/call-optimization.h"
|
| -#include "src/ic/ic-compiler.h"
|
| +#include "src/ic/handler-compiler.h"
|
|
|
| namespace v8 {
|
| namespace internal {
|
|
|
| #define __ ACCESS_MASM(masm)
|
|
|
| -
|
| void PropertyHandlerCompiler::GenerateDictionaryNegativeLookup(
|
| MacroAssembler* masm, Label* miss_label, Register receiver,
|
| Handle<Name> name, Register scratch0, Register scratch1) {
|
| @@ -199,6 +198,127 @@ void PropertyHandlerCompiler::GenerateCheckPropertyCell(
|
| }
|
|
|
|
|
| +void NamedStoreHandlerCompiler::GenerateStoreViaSetter(
|
| + MacroAssembler* masm, Handle<HeapType> type, Register receiver,
|
| + Handle<JSFunction> setter) {
|
| + // ----------- S t a t e -------------
|
| + // -- rsp[0] : return address
|
| + // -----------------------------------
|
| + {
|
| + FrameScope scope(masm, StackFrame::INTERNAL);
|
| +
|
| + // Save value register, so we can restore it later.
|
| + __ Push(value());
|
| +
|
| + if (!setter.is_null()) {
|
| + // Call the JavaScript setter with receiver and value on the stack.
|
| + if (IC::TypeToMap(*type, masm->isolate())->IsJSGlobalObjectMap()) {
|
| + // Swap in the global receiver.
|
| + __ movp(receiver,
|
| + FieldOperand(receiver, JSGlobalObject::kGlobalProxyOffset));
|
| + }
|
| + __ Push(receiver);
|
| + __ Push(value());
|
| + ParameterCount actual(1);
|
| + ParameterCount expected(setter);
|
| + __ InvokeFunction(setter, expected, actual, CALL_FUNCTION,
|
| + NullCallWrapper());
|
| + } else {
|
| + // If we generate a global code snippet for deoptimization only, remember
|
| + // the place to continue after deoptimization.
|
| + masm->isolate()->heap()->SetSetterStubDeoptPCOffset(masm->pc_offset());
|
| + }
|
| +
|
| + // We have to return the passed value, not the return value of the setter.
|
| + __ Pop(rax);
|
| +
|
| + // Restore context register.
|
| + __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
|
| + }
|
| + __ ret(0);
|
| +}
|
| +
|
| +
|
| +void NamedLoadHandlerCompiler::GenerateLoadViaGetter(
|
| + MacroAssembler* masm, Handle<HeapType> type, Register receiver,
|
| + Handle<JSFunction> getter) {
|
| + // ----------- S t a t e -------------
|
| + // -- rax : receiver
|
| + // -- rcx : name
|
| + // -- rsp[0] : return address
|
| + // -----------------------------------
|
| + {
|
| + FrameScope scope(masm, StackFrame::INTERNAL);
|
| +
|
| + if (!getter.is_null()) {
|
| + // Call the JavaScript getter with the receiver on the stack.
|
| + if (IC::TypeToMap(*type, masm->isolate())->IsJSGlobalObjectMap()) {
|
| + // Swap in the global receiver.
|
| + __ movp(receiver,
|
| + FieldOperand(receiver, JSGlobalObject::kGlobalProxyOffset));
|
| + }
|
| + __ Push(receiver);
|
| + ParameterCount actual(0);
|
| + ParameterCount expected(getter);
|
| + __ InvokeFunction(getter, expected, actual, CALL_FUNCTION,
|
| + NullCallWrapper());
|
| + } else {
|
| + // If we generate a global code snippet for deoptimization only, remember
|
| + // the place to continue after deoptimization.
|
| + masm->isolate()->heap()->SetGetterStubDeoptPCOffset(masm->pc_offset());
|
| + }
|
| +
|
| + // Restore context register.
|
| + __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
|
| + }
|
| + __ ret(0);
|
| +}
|
| +
|
| +
|
| +void ElementHandlerCompiler::GenerateLoadDictionaryElement(
|
| + MacroAssembler* masm) {
|
| + // ----------- S t a t e -------------
|
| + // -- rcx : key
|
| + // -- rdx : receiver
|
| + // -- rsp[0] : return address
|
| + // -----------------------------------
|
| + DCHECK(rdx.is(LoadIC::ReceiverRegister()));
|
| + DCHECK(rcx.is(LoadIC::NameRegister()));
|
| + Label slow, miss;
|
| +
|
| + // This stub is meant to be tail-jumped to, the receiver must already
|
| + // have been verified by the caller to not be a smi.
|
| +
|
| + __ JumpIfNotSmi(rcx, &miss);
|
| + __ SmiToInteger32(rbx, rcx);
|
| + __ movp(rax, FieldOperand(rdx, JSObject::kElementsOffset));
|
| +
|
| + // Check whether the elements is a number dictionary.
|
| + // rdx: receiver
|
| + // rcx: key
|
| + // rbx: key as untagged int32
|
| + // rax: elements
|
| + __ LoadFromNumberDictionary(&slow, rax, rcx, rbx, r9, rdi, rax);
|
| + __ ret(0);
|
| +
|
| + __ bind(&slow);
|
| + // ----------- S t a t e -------------
|
| + // -- rcx : key
|
| + // -- rdx : receiver
|
| + // -- rsp[0] : return address
|
| + // -----------------------------------
|
| + TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Slow);
|
| +
|
| + __ bind(&miss);
|
| + // ----------- S t a t e -------------
|
| + // -- rcx : key
|
| + // -- rdx : receiver
|
| + // -- rsp[0] : return address
|
| + // -----------------------------------
|
| + TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss);
|
| +}
|
| +
|
| +
|
| #undef __
|
| #define __ ACCESS_MASM((masm()))
|
|
|
| @@ -664,55 +784,6 @@ Handle<Code> NamedStoreHandlerCompiler::CompileStoreCallback(
|
| }
|
|
|
|
|
| -#undef __
|
| -#define __ ACCESS_MASM(masm)
|
| -
|
| -
|
| -void NamedStoreHandlerCompiler::GenerateStoreViaSetter(
|
| - MacroAssembler* masm, Handle<HeapType> type, Register receiver,
|
| - Handle<JSFunction> setter) {
|
| - // ----------- S t a t e -------------
|
| - // -- rsp[0] : return address
|
| - // -----------------------------------
|
| - {
|
| - FrameScope scope(masm, StackFrame::INTERNAL);
|
| -
|
| - // Save value register, so we can restore it later.
|
| - __ Push(value());
|
| -
|
| - if (!setter.is_null()) {
|
| - // Call the JavaScript setter with receiver and value on the stack.
|
| - if (IC::TypeToMap(*type, masm->isolate())->IsJSGlobalObjectMap()) {
|
| - // Swap in the global receiver.
|
| - __ movp(receiver,
|
| - FieldOperand(receiver, JSGlobalObject::kGlobalProxyOffset));
|
| - }
|
| - __ Push(receiver);
|
| - __ Push(value());
|
| - ParameterCount actual(1);
|
| - ParameterCount expected(setter);
|
| - __ InvokeFunction(setter, expected, actual, CALL_FUNCTION,
|
| - NullCallWrapper());
|
| - } else {
|
| - // If we generate a global code snippet for deoptimization only, remember
|
| - // the place to continue after deoptimization.
|
| - masm->isolate()->heap()->SetSetterStubDeoptPCOffset(masm->pc_offset());
|
| - }
|
| -
|
| - // We have to return the passed value, not the return value of the setter.
|
| - __ Pop(rax);
|
| -
|
| - // Restore context register.
|
| - __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
|
| - }
|
| - __ ret(0);
|
| -}
|
| -
|
| -
|
| -#undef __
|
| -#define __ ACCESS_MASM(masm())
|
| -
|
| -
|
| Handle<Code> NamedStoreHandlerCompiler::CompileStoreInterceptor(
|
| Handle<Name> name) {
|
| __ PopReturnAddressTo(scratch1());
|
| @@ -731,85 +802,9 @@ Handle<Code> NamedStoreHandlerCompiler::CompileStoreInterceptor(
|
| }
|
|
|
|
|
| -Handle<Code> PropertyICCompiler::CompileKeyedStorePolymorphic(
|
| - MapHandleList* receiver_maps, CodeHandleList* handler_stubs,
|
| - MapHandleList* transitioned_maps) {
|
| - Label miss;
|
| - __ JumpIfSmi(receiver(), &miss, Label::kNear);
|
| -
|
| - __ movp(scratch1(), FieldOperand(receiver(), HeapObject::kMapOffset));
|
| - int receiver_count = receiver_maps->length();
|
| - for (int i = 0; i < receiver_count; ++i) {
|
| - // Check map and tail call if there's a match
|
| - __ Cmp(scratch1(), receiver_maps->at(i));
|
| - if (transitioned_maps->at(i).is_null()) {
|
| - __ j(equal, handler_stubs->at(i), RelocInfo::CODE_TARGET);
|
| - } else {
|
| - Label next_map;
|
| - __ j(not_equal, &next_map, Label::kNear);
|
| - __ Move(transition_map(), transitioned_maps->at(i),
|
| - RelocInfo::EMBEDDED_OBJECT);
|
| - __ jmp(handler_stubs->at(i), RelocInfo::CODE_TARGET);
|
| - __ bind(&next_map);
|
| - }
|
| - }
|
| -
|
| - __ bind(&miss);
|
| -
|
| - TailCallBuiltin(masm(), MissBuiltin(kind()));
|
| -
|
| - // Return the generated code.
|
| - return GetCode(kind(), Code::NORMAL, factory()->empty_string(), POLYMORPHIC);
|
| -}
|
| -
|
| -
|
| Register NamedStoreHandlerCompiler::value() { return StoreIC::ValueRegister(); }
|
|
|
|
|
| -#undef __
|
| -#define __ ACCESS_MASM(masm)
|
| -
|
| -
|
| -void NamedLoadHandlerCompiler::GenerateLoadViaGetter(
|
| - MacroAssembler* masm, Handle<HeapType> type, Register receiver,
|
| - Handle<JSFunction> getter) {
|
| - // ----------- S t a t e -------------
|
| - // -- rax : receiver
|
| - // -- rcx : name
|
| - // -- rsp[0] : return address
|
| - // -----------------------------------
|
| - {
|
| - FrameScope scope(masm, StackFrame::INTERNAL);
|
| -
|
| - if (!getter.is_null()) {
|
| - // Call the JavaScript getter with the receiver on the stack.
|
| - if (IC::TypeToMap(*type, masm->isolate())->IsJSGlobalObjectMap()) {
|
| - // Swap in the global receiver.
|
| - __ movp(receiver,
|
| - FieldOperand(receiver, JSGlobalObject::kGlobalProxyOffset));
|
| - }
|
| - __ Push(receiver);
|
| - ParameterCount actual(0);
|
| - ParameterCount expected(getter);
|
| - __ InvokeFunction(getter, expected, actual, CALL_FUNCTION,
|
| - NullCallWrapper());
|
| - } else {
|
| - // If we generate a global code snippet for deoptimization only, remember
|
| - // the place to continue after deoptimization.
|
| - masm->isolate()->heap()->SetGetterStubDeoptPCOffset(masm->pc_offset());
|
| - }
|
| -
|
| - // Restore context register.
|
| - __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
|
| - }
|
| - __ ret(0);
|
| -}
|
| -
|
| -
|
| -#undef __
|
| -#define __ ACCESS_MASM(masm())
|
| -
|
| -
|
| Handle<Code> NamedLoadHandlerCompiler::CompileLoadGlobal(
|
| Handle<PropertyCell> cell, Handle<Name> name, bool is_configurable) {
|
| Label miss;
|
| @@ -840,128 +835,6 @@ Handle<Code> NamedLoadHandlerCompiler::CompileLoadGlobal(
|
| }
|
|
|
|
|
| -Handle<Code> PropertyICCompiler::CompilePolymorphic(TypeHandleList* types,
|
| - CodeHandleList* handlers,
|
| - Handle<Name> name,
|
| - Code::StubType type,
|
| - IcCheckType check) {
|
| - Label miss;
|
| -
|
| - if (check == PROPERTY &&
|
| - (kind() == Code::KEYED_LOAD_IC || kind() == Code::KEYED_STORE_IC)) {
|
| - // In case we are compiling an IC for dictionary loads and stores, just
|
| - // check whether the name is unique.
|
| - if (name.is_identical_to(isolate()->factory()->normal_ic_symbol())) {
|
| - __ JumpIfNotUniqueName(this->name(), &miss);
|
| - } else {
|
| - __ Cmp(this->name(), name);
|
| - __ j(not_equal, &miss);
|
| - }
|
| - }
|
| -
|
| - Label number_case;
|
| - Label* smi_target = IncludesNumberType(types) ? &number_case : &miss;
|
| - __ JumpIfSmi(receiver(), smi_target);
|
| -
|
| - // Polymorphic keyed stores may use the map register
|
| - Register map_reg = scratch1();
|
| - DCHECK(kind() != Code::KEYED_STORE_IC ||
|
| - map_reg.is(KeyedStoreIC::MapRegister()));
|
| - __ movp(map_reg, FieldOperand(receiver(), HeapObject::kMapOffset));
|
| - int receiver_count = types->length();
|
| - int number_of_handled_maps = 0;
|
| - for (int current = 0; current < receiver_count; ++current) {
|
| - Handle<HeapType> type = types->at(current);
|
| - Handle<Map> map = IC::TypeToMap(*type, isolate());
|
| - if (!map->is_deprecated()) {
|
| - number_of_handled_maps++;
|
| - // Check map and tail call if there's a match
|
| - __ Cmp(map_reg, map);
|
| - if (type->Is(HeapType::Number())) {
|
| - DCHECK(!number_case.is_unused());
|
| - __ bind(&number_case);
|
| - }
|
| - __ j(equal, handlers->at(current), RelocInfo::CODE_TARGET);
|
| - }
|
| - }
|
| - DCHECK(number_of_handled_maps > 0);
|
| -
|
| - __ bind(&miss);
|
| - TailCallBuiltin(masm(), MissBuiltin(kind()));
|
| -
|
| - // Return the generated code.
|
| - InlineCacheState state =
|
| - number_of_handled_maps > 1 ? POLYMORPHIC : MONOMORPHIC;
|
| - return GetCode(kind(), type, name, state);
|
| -}
|
| -
|
| -
|
| -#undef __
|
| -#define __ ACCESS_MASM(masm)
|
| -
|
| -
|
| -void ElementHandlerCompiler::GenerateLoadDictionaryElement(
|
| - MacroAssembler* masm) {
|
| - // ----------- S t a t e -------------
|
| - // -- rcx : key
|
| - // -- rdx : receiver
|
| - // -- rsp[0] : return address
|
| - // -----------------------------------
|
| - DCHECK(rdx.is(LoadIC::ReceiverRegister()));
|
| - DCHECK(rcx.is(LoadIC::NameRegister()));
|
| - Label slow, miss;
|
| -
|
| - // This stub is meant to be tail-jumped to, the receiver must already
|
| - // have been verified by the caller to not be a smi.
|
| -
|
| - __ JumpIfNotSmi(rcx, &miss);
|
| - __ SmiToInteger32(rbx, rcx);
|
| - __ movp(rax, FieldOperand(rdx, JSObject::kElementsOffset));
|
| -
|
| - // Check whether the elements is a number dictionary.
|
| - // rdx: receiver
|
| - // rcx: key
|
| - // rbx: key as untagged int32
|
| - // rax: elements
|
| - __ LoadFromNumberDictionary(&slow, rax, rcx, rbx, r9, rdi, rax);
|
| - __ ret(0);
|
| -
|
| - __ bind(&slow);
|
| - // ----------- S t a t e -------------
|
| - // -- rcx : key
|
| - // -- rdx : receiver
|
| - // -- rsp[0] : return address
|
| - // -----------------------------------
|
| - TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Slow);
|
| -
|
| - __ bind(&miss);
|
| - // ----------- S t a t e -------------
|
| - // -- rcx : key
|
| - // -- rdx : receiver
|
| - // -- rsp[0] : return address
|
| - // -----------------------------------
|
| - TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss);
|
| -}
|
| -
|
| -
|
| -void PropertyICCompiler::GenerateRuntimeSetProperty(MacroAssembler* masm,
|
| - StrictMode strict_mode) {
|
| - // Return address is on the stack.
|
| - DCHECK(!rbx.is(StoreIC::ReceiverRegister()) &&
|
| - !rbx.is(StoreIC::NameRegister()) && !rbx.is(StoreIC::ValueRegister()));
|
| -
|
| - __ PopReturnAddressTo(rbx);
|
| - __ Push(StoreIC::ReceiverRegister());
|
| - __ Push(StoreIC::NameRegister());
|
| - __ Push(StoreIC::ValueRegister());
|
| - __ Push(Smi::FromInt(strict_mode));
|
| - __ PushReturnAddressFrom(rbx);
|
| -
|
| - // Do tail-call to runtime routine.
|
| - __ TailCallRuntime(Runtime::kSetProperty, 4, 1);
|
| -}
|
| -
|
| -
|
| #undef __
|
| }
|
| } // namespace v8::internal
|
|
|