| Index: src/ic/arm64/handler-compiler-arm64.cc
|
| diff --git a/src/ic/arm64/ic-compiler-arm64.cc b/src/ic/arm64/handler-compiler-arm64.cc
|
| similarity index 88%
|
| copy from src/ic/arm64/ic-compiler-arm64.cc
|
| copy to src/ic/arm64/handler-compiler-arm64.cc
|
| index 3e7f8f50a0a39c8d00819b70d103f7d1a7605aa1..e0678db6870952d37c2f8a4328e4c264f8b7ef42 100644
|
| --- a/src/ic/arm64/ic-compiler-arm64.cc
|
| +++ b/src/ic/arm64/handler-compiler-arm64.cc
|
| @@ -7,7 +7,7 @@
|
| #if V8_TARGET_ARCH_ARM64
|
|
|
| #include "src/ic/call-optimization.h"
|
| -#include "src/ic/ic-compiler.h"
|
| +#include "src/ic/handler-compiler.h"
|
|
|
| namespace v8 {
|
| namespace internal {
|
| @@ -206,10 +206,157 @@ void PropertyHandlerCompiler::GenerateFastApiCall(
|
| }
|
|
|
|
|
| +void NamedStoreHandlerCompiler::GenerateStoreViaSetter(
|
| + MacroAssembler* masm, Handle<HeapType> type, Register receiver,
|
| + Handle<JSFunction> setter) {
|
| + // ----------- S t a t e -------------
|
| + // -- lr : return address
|
| + // -----------------------------------
|
| + Label miss;
|
| +
|
| + {
|
| + 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.
|
| + __ Ldr(receiver,
|
| + FieldMemOperand(receiver, JSGlobalObject::kGlobalProxyOffset));
|
| + }
|
| + __ Push(receiver, 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(x0);
|
| +
|
| + // Restore context register.
|
| + __ Ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
|
| + }
|
| + __ Ret();
|
| +}
|
| +
|
| +
|
| +void NamedLoadHandlerCompiler::GenerateLoadViaGetter(
|
| + MacroAssembler* masm, Handle<HeapType> type, Register receiver,
|
| + Handle<JSFunction> getter) {
|
| + {
|
| + 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.
|
| + __ Ldr(receiver,
|
| + FieldMemOperand(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.
|
| + __ Ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
|
| + }
|
| + __ Ret();
|
| +}
|
| +
|
| +
|
| +void ElementHandlerCompiler::GenerateLoadDictionaryElement(
|
| + MacroAssembler* masm) {
|
| + // The return address is in lr.
|
| + Label slow, miss;
|
| +
|
| + Register result = x0;
|
| + Register key = LoadIC::NameRegister();
|
| + Register receiver = LoadIC::ReceiverRegister();
|
| + DCHECK(receiver.is(x1));
|
| + DCHECK(key.is(x2));
|
| +
|
| + __ JumpIfNotSmi(key, &miss);
|
| + __ Ldr(x4, FieldMemOperand(receiver, JSObject::kElementsOffset));
|
| + __ LoadFromNumberDictionary(&slow, x4, key, result, x7, x3, x5, x6);
|
| + __ Ret();
|
| +
|
| + __ Bind(&slow);
|
| + __ IncrementCounter(
|
| + masm->isolate()->counters()->keyed_load_external_array_slow(), 1, x4, x3);
|
| + TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Slow);
|
| +
|
| + // Miss case, call the runtime.
|
| + __ Bind(&miss);
|
| + TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss);
|
| +}
|
| +
|
| +
|
| #undef __
|
| #define __ ACCESS_MASM(masm())
|
|
|
|
|
| +Handle<Code> NamedLoadHandlerCompiler::CompileLoadGlobal(
|
| + Handle<PropertyCell> cell, Handle<Name> name, bool is_configurable) {
|
| + Label miss;
|
| + FrontendHeader(receiver(), name, &miss);
|
| +
|
| + // Get the value from the cell.
|
| + Register result = StoreIC::ValueRegister();
|
| + __ Mov(result, Operand(cell));
|
| + __ Ldr(result, FieldMemOperand(result, Cell::kValueOffset));
|
| +
|
| + // Check for deleted property if property can actually be deleted.
|
| + if (is_configurable) {
|
| + __ JumpIfRoot(result, Heap::kTheHoleValueRootIndex, &miss);
|
| + }
|
| +
|
| + Counters* counters = isolate()->counters();
|
| + __ IncrementCounter(counters->named_load_global_stub(), 1, x1, x3);
|
| + __ Ret();
|
| +
|
| + FrontendFooter(name, &miss);
|
| +
|
| + // Return the generated code.
|
| + return GetCode(kind(), Code::NORMAL, name);
|
| +}
|
| +
|
| +
|
| +Handle<Code> NamedStoreHandlerCompiler::CompileStoreInterceptor(
|
| + Handle<Name> name) {
|
| + Label miss;
|
| +
|
| + ASM_LOCATION("NamedStoreHandlerCompiler::CompileStoreInterceptor");
|
| +
|
| + __ Push(receiver(), this->name(), value());
|
| +
|
| + // Do tail-call to the runtime system.
|
| + ExternalReference store_ic_property = ExternalReference(
|
| + IC_Utility(IC::kStorePropertyWithInterceptor), isolate());
|
| + __ TailCallExternalReference(store_ic_property, 3, 1);
|
| +
|
| + // Return the generated code.
|
| + return GetCode(kind(), Code::FAST, name);
|
| +}
|
| +
|
| +
|
| +Register NamedStoreHandlerCompiler::value() { return StoreIC::ValueRegister(); }
|
| +
|
| +
|
| void NamedStoreHandlerCompiler::GenerateRestoreName(Label* label,
|
| Handle<Name> name) {
|
| if (!label->is_unused()) {
|
| @@ -691,276 +838,7 @@ 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 -------------
|
| - // -- lr : return address
|
| - // -----------------------------------
|
| - Label miss;
|
| -
|
| - {
|
| - 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.
|
| - __ Ldr(receiver,
|
| - FieldMemOperand(receiver, JSGlobalObject::kGlobalProxyOffset));
|
| - }
|
| - __ Push(receiver, 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(x0);
|
| -
|
| - // Restore context register.
|
| - __ Ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
|
| - }
|
| - __ Ret();
|
| -}
|
| -
|
| -
|
| -#undef __
|
| -#define __ ACCESS_MASM(masm())
|
| -
|
| -
|
| -Handle<Code> NamedStoreHandlerCompiler::CompileStoreInterceptor(
|
| - Handle<Name> name) {
|
| - Label miss;
|
| -
|
| - ASM_LOCATION("NamedStoreHandlerCompiler::CompileStoreInterceptor");
|
| -
|
| - __ Push(receiver(), this->name(), value());
|
| -
|
| - // Do tail-call to the runtime system.
|
| - ExternalReference store_ic_property = ExternalReference(
|
| - IC_Utility(IC::kStorePropertyWithInterceptor), isolate());
|
| - __ TailCallExternalReference(store_ic_property, 3, 1);
|
| -
|
| - // Return the generated code.
|
| - return GetCode(kind(), Code::FAST, name);
|
| -}
|
| -
|
| -
|
| -Register NamedStoreHandlerCompiler::value() { return StoreIC::ValueRegister(); }
|
| -
|
| -
|
| -#undef __
|
| -#define __ ACCESS_MASM(masm)
|
| -
|
| -void NamedLoadHandlerCompiler::GenerateLoadViaGetter(
|
| - MacroAssembler* masm, Handle<HeapType> type, Register receiver,
|
| - Handle<JSFunction> getter) {
|
| - {
|
| - 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.
|
| - __ Ldr(receiver,
|
| - FieldMemOperand(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.
|
| - __ Ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
|
| - }
|
| - __ Ret();
|
| -}
|
| -
|
| -
|
| -#undef __
|
| -#define __ ACCESS_MASM(masm())
|
| -
|
| -
|
| -Handle<Code> NamedLoadHandlerCompiler::CompileLoadGlobal(
|
| - Handle<PropertyCell> cell, Handle<Name> name, bool is_configurable) {
|
| - Label miss;
|
| - FrontendHeader(receiver(), name, &miss);
|
| -
|
| - // Get the value from the cell.
|
| - Register result = StoreIC::ValueRegister();
|
| - __ Mov(result, Operand(cell));
|
| - __ Ldr(result, FieldMemOperand(result, Cell::kValueOffset));
|
| -
|
| - // Check for deleted property if property can actually be deleted.
|
| - if (is_configurable) {
|
| - __ JumpIfRoot(result, Heap::kTheHoleValueRootIndex, &miss);
|
| - }
|
| -
|
| - Counters* counters = isolate()->counters();
|
| - __ IncrementCounter(counters->named_load_global_stub(), 1, x1, x3);
|
| - __ Ret();
|
| -
|
| - FrontendFooter(name, &miss);
|
| -
|
| - // Return the generated code.
|
| - return GetCode(kind(), Code::NORMAL, name);
|
| -}
|
| -
|
| -
|
| -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 {
|
| - __ CompareAndBranch(this->name(), Operand(name), ne, &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()));
|
| - __ Ldr(map_reg, FieldMemOperand(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++;
|
| - Label try_next;
|
| - __ Cmp(map_reg, Operand(map));
|
| - __ B(ne, &try_next);
|
| - if (type->Is(HeapType::Number())) {
|
| - DCHECK(!number_case.is_unused());
|
| - __ Bind(&number_case);
|
| - }
|
| - __ Jump(handlers->at(current), RelocInfo::CODE_TARGET);
|
| - __ Bind(&try_next);
|
| - }
|
| - }
|
| - 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);
|
| -}
|
| -
|
| -
|
| -Handle<Code> PropertyICCompiler::CompileKeyedStorePolymorphic(
|
| - MapHandleList* receiver_maps, CodeHandleList* handler_stubs,
|
| - MapHandleList* transitioned_maps) {
|
| - Label miss;
|
| -
|
| - ASM_LOCATION("PropertyICCompiler::CompileStorePolymorphic");
|
| -
|
| - __ JumpIfSmi(receiver(), &miss);
|
| -
|
| - int receiver_count = receiver_maps->length();
|
| - __ Ldr(scratch1(), FieldMemOperand(receiver(), HeapObject::kMapOffset));
|
| - for (int i = 0; i < receiver_count; i++) {
|
| - __ Cmp(scratch1(), Operand(receiver_maps->at(i)));
|
| -
|
| - Label skip;
|
| - __ B(&skip, ne);
|
| - if (!transitioned_maps->at(i).is_null()) {
|
| - // This argument is used by the handler stub. For example, see
|
| - // ElementsTransitionGenerator::GenerateMapChangeElementsTransition.
|
| - __ Mov(transition_map(), Operand(transitioned_maps->at(i)));
|
| - }
|
| - __ Jump(handler_stubs->at(i), RelocInfo::CODE_TARGET);
|
| - __ Bind(&skip);
|
| - }
|
| -
|
| - __ Bind(&miss);
|
| - TailCallBuiltin(masm(), MissBuiltin(kind()));
|
| -
|
| - return GetCode(kind(), Code::NORMAL, factory()->empty_string(), POLYMORPHIC);
|
| -}
|
| -
|
| -
|
| -#undef __
|
| -#define __ ACCESS_MASM(masm)
|
| -
|
| -void ElementHandlerCompiler::GenerateLoadDictionaryElement(
|
| - MacroAssembler* masm) {
|
| - // The return address is in lr.
|
| - Label slow, miss;
|
| -
|
| - Register result = x0;
|
| - Register key = LoadIC::NameRegister();
|
| - Register receiver = LoadIC::ReceiverRegister();
|
| - DCHECK(receiver.is(x1));
|
| - DCHECK(key.is(x2));
|
| -
|
| - __ JumpIfNotSmi(key, &miss);
|
| - __ Ldr(x4, FieldMemOperand(receiver, JSObject::kElementsOffset));
|
| - __ LoadFromNumberDictionary(&slow, x4, key, result, x7, x3, x5, x6);
|
| - __ Ret();
|
| -
|
| - __ Bind(&slow);
|
| - __ IncrementCounter(
|
| - masm->isolate()->counters()->keyed_load_external_array_slow(), 1, x4, x3);
|
| - TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Slow);
|
| -
|
| - // Miss case, call the runtime.
|
| - __ Bind(&miss);
|
| - TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss);
|
| -}
|
| -
|
| -
|
| -void PropertyICCompiler::GenerateRuntimeSetProperty(MacroAssembler* masm,
|
| - StrictMode strict_mode) {
|
| - ASM_LOCATION("PropertyICCompiler::GenerateRuntimeSetProperty");
|
| -
|
| - __ Push(StoreIC::ReceiverRegister(), StoreIC::NameRegister(),
|
| - StoreIC::ValueRegister());
|
| -
|
| - __ Mov(x10, Smi::FromInt(strict_mode));
|
| - __ Push(x10);
|
| -
|
| - // Do tail-call to runtime routine.
|
| - __ TailCallRuntime(Runtime::kSetProperty, 4, 1);
|
| -}
|
| -
|
| -
|
| -#undef __
|
| }
|
| } // namespace v8::internal
|
|
|
| -#endif // V8_TARGET_ARCH_ARM64
|
| +#endif // V8_TARGET_ARCH_IA32
|
|
|