| Index: src/ic/ia32/handler-compiler-ia32.cc
|
| diff --git a/src/ic/ia32/ic-compiler-ia32.cc b/src/ic/ia32/handler-compiler-ia32.cc
|
| similarity index 88%
|
| copy from src/ic/ia32/ic-compiler-ia32.cc
|
| copy to src/ic/ia32/handler-compiler-ia32.cc
|
| index fb1542dfc11fcbe10d2d12e90dd7e2b4f1a29445..0db5485d715b75d3be4eb2939137c352ace27de2 100644
|
| --- a/src/ic/ia32/ic-compiler-ia32.cc
|
| +++ b/src/ic/ia32/handler-compiler-ia32.cc
|
| @@ -7,13 +7,91 @@
|
| #if V8_TARGET_ARCH_IA32
|
|
|
| #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 ElementHandlerCompiler::GenerateLoadDictionaryElement(
|
| + MacroAssembler* masm) {
|
| + // ----------- S t a t e -------------
|
| + // -- ecx : key
|
| + // -- edx : receiver
|
| + // -- esp[0] : return address
|
| + // -----------------------------------
|
| + DCHECK(edx.is(LoadIC::ReceiverRegister()));
|
| + DCHECK(ecx.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(ecx, &miss);
|
| + __ mov(ebx, ecx);
|
| + __ SmiUntag(ebx);
|
| + __ mov(eax, FieldOperand(edx, JSObject::kElementsOffset));
|
| +
|
| + // Push receiver on the stack to free up a register for the dictionary
|
| + // probing.
|
| + __ push(edx);
|
| + __ LoadFromNumberDictionary(&slow, eax, ecx, ebx, edx, edi, eax);
|
| + // Pop receiver before returning.
|
| + __ pop(edx);
|
| + __ ret(0);
|
| +
|
| + __ bind(&slow);
|
| + __ pop(edx);
|
| +
|
| + // ----------- S t a t e -------------
|
| + // -- ecx : key
|
| + // -- edx : receiver
|
| + // -- esp[0] : return address
|
| + // -----------------------------------
|
| + TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Slow);
|
| +
|
| + __ bind(&miss);
|
| + // ----------- S t a t e -------------
|
| + // -- ecx : key
|
| + // -- edx : receiver
|
| + // -- esp[0] : return address
|
| + // -----------------------------------
|
| + TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss);
|
| +}
|
| +
|
| +
|
| +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.
|
| + __ mov(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.
|
| + __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
|
| + }
|
| + __ ret(0);
|
| +}
|
| +
|
| +
|
| void PropertyHandlerCompiler::GenerateDictionaryNegativeLookup(
|
| MacroAssembler* masm, Label* miss_label, Register receiver,
|
| Handle<Name> name, Register scratch0, Register scratch1) {
|
| @@ -83,34 +161,6 @@ void NamedLoadHandlerCompiler::GenerateLoadFunctionPrototype(
|
| }
|
|
|
|
|
| -static void PushInterceptorArguments(MacroAssembler* masm, Register receiver,
|
| - Register holder, Register name,
|
| - Handle<JSObject> holder_obj) {
|
| - STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsNameIndex == 0);
|
| - STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsInfoIndex == 1);
|
| - STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsThisIndex == 2);
|
| - STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsHolderIndex == 3);
|
| - STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsLength == 4);
|
| - __ push(name);
|
| - Handle<InterceptorInfo> interceptor(holder_obj->GetNamedInterceptor());
|
| - DCHECK(!masm->isolate()->heap()->InNewSpace(*interceptor));
|
| - Register scratch = name;
|
| - __ mov(scratch, Immediate(interceptor));
|
| - __ push(scratch);
|
| - __ push(receiver);
|
| - __ push(holder);
|
| -}
|
| -
|
| -
|
| -static void CompileCallLoadPropertyWithInterceptor(
|
| - MacroAssembler* masm, Register receiver, Register holder, Register name,
|
| - Handle<JSObject> holder_obj, IC::UtilityId id) {
|
| - PushInterceptorArguments(masm, receiver, holder, name, holder_obj);
|
| - __ CallExternalReference(ExternalReference(IC_Utility(id), masm->isolate()),
|
| - NamedLoadHandlerCompiler::kInterceptorArgsLength);
|
| -}
|
| -
|
| -
|
| // Generate call to api function.
|
| // This function uses push() to generate smaller, faster code than
|
| // the version above. It is an optimization that should will be removed
|
| @@ -207,6 +257,75 @@ void PropertyHandlerCompiler::GenerateCheckPropertyCell(
|
| }
|
|
|
|
|
| +void NamedStoreHandlerCompiler::GenerateStoreViaSetter(
|
| + MacroAssembler* masm, Handle<HeapType> type, Register receiver,
|
| + Handle<JSFunction> setter) {
|
| + // ----------- S t a t e -------------
|
| + // -- esp[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.
|
| + __ mov(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(eax);
|
| +
|
| + // Restore context register.
|
| + __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
|
| + }
|
| + __ ret(0);
|
| +}
|
| +
|
| +
|
| +static void PushInterceptorArguments(MacroAssembler* masm, Register receiver,
|
| + Register holder, Register name,
|
| + Handle<JSObject> holder_obj) {
|
| + STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsNameIndex == 0);
|
| + STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsInfoIndex == 1);
|
| + STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsThisIndex == 2);
|
| + STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsHolderIndex == 3);
|
| + STATIC_ASSERT(NamedLoadHandlerCompiler::kInterceptorArgsLength == 4);
|
| + __ push(name);
|
| + Handle<InterceptorInfo> interceptor(holder_obj->GetNamedInterceptor());
|
| + DCHECK(!masm->isolate()->heap()->InNewSpace(*interceptor));
|
| + Register scratch = name;
|
| + __ mov(scratch, Immediate(interceptor));
|
| + __ push(scratch);
|
| + __ push(receiver);
|
| + __ push(holder);
|
| +}
|
| +
|
| +
|
| +static void CompileCallLoadPropertyWithInterceptor(
|
| + MacroAssembler* masm, Register receiver, Register holder, Register name,
|
| + Handle<JSObject> holder_obj, IC::UtilityId id) {
|
| + PushInterceptorArguments(masm, receiver, holder, name, holder_obj);
|
| + __ CallExternalReference(ExternalReference(IC_Utility(id), masm->isolate()),
|
| + NamedLoadHandlerCompiler::kInterceptorArgsLength);
|
| +}
|
| +
|
| +
|
| #undef __
|
| #define __ ACCESS_MASM(masm())
|
|
|
| @@ -680,55 +799,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 -------------
|
| - // -- esp[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.
|
| - __ mov(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(eax);
|
| -
|
| - // Restore context register.
|
| - __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
|
| - }
|
| - __ ret(0);
|
| -}
|
| -
|
| -
|
| -#undef __
|
| -#define __ ACCESS_MASM(masm())
|
| -
|
| -
|
| Handle<Code> NamedStoreHandlerCompiler::CompileStoreInterceptor(
|
| Handle<Name> name) {
|
| __ pop(scratch1()); // remove the return address
|
| @@ -747,74 +817,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);
|
| - __ mov(scratch1(), FieldOperand(receiver(), HeapObject::kMapOffset));
|
| - for (int i = 0; i < receiver_maps->length(); ++i) {
|
| - __ cmp(scratch1(), receiver_maps->at(i));
|
| - if (transitioned_maps->at(i).is_null()) {
|
| - __ j(equal, handler_stubs->at(i));
|
| - } else {
|
| - Label next_map;
|
| - __ j(not_equal, &next_map, Label::kNear);
|
| - __ mov(transition_map(), Immediate(transitioned_maps->at(i)));
|
| - __ 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) {
|
| - {
|
| - 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.
|
| - __ mov(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.
|
| - __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
|
| - }
|
| - __ ret(0);
|
| -}
|
| -
|
| -
|
| -#undef __
|
| -#define __ ACCESS_MASM(masm())
|
| -
|
| -
|
| Handle<Code> NamedLoadHandlerCompiler::CompileLoadGlobal(
|
| Handle<PropertyCell> cell, Handle<Name> name, bool is_configurable) {
|
| Label miss;
|
| @@ -850,128 +855,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(), Immediate(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()));
|
| - __ mov(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++;
|
| - __ cmp(map_reg, map);
|
| - if (type->Is(HeapType::Number())) {
|
| - DCHECK(!number_case.is_unused());
|
| - __ bind(&number_case);
|
| - }
|
| - __ j(equal, handlers->at(current));
|
| - }
|
| - }
|
| - 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 -------------
|
| - // -- ecx : key
|
| - // -- edx : receiver
|
| - // -- esp[0] : return address
|
| - // -----------------------------------
|
| - DCHECK(edx.is(LoadIC::ReceiverRegister()));
|
| - DCHECK(ecx.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(ecx, &miss);
|
| - __ mov(ebx, ecx);
|
| - __ SmiUntag(ebx);
|
| - __ mov(eax, FieldOperand(edx, JSObject::kElementsOffset));
|
| -
|
| - // Push receiver on the stack to free up a register for the dictionary
|
| - // probing.
|
| - __ push(edx);
|
| - __ LoadFromNumberDictionary(&slow, eax, ecx, ebx, edx, edi, eax);
|
| - // Pop receiver before returning.
|
| - __ pop(edx);
|
| - __ ret(0);
|
| -
|
| - __ bind(&slow);
|
| - __ pop(edx);
|
| -
|
| - // ----------- S t a t e -------------
|
| - // -- ecx : key
|
| - // -- edx : receiver
|
| - // -- esp[0] : return address
|
| - // -----------------------------------
|
| - TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Slow);
|
| -
|
| - __ bind(&miss);
|
| - // ----------- S t a t e -------------
|
| - // -- ecx : key
|
| - // -- edx : receiver
|
| - // -- esp[0] : return address
|
| - // -----------------------------------
|
| - TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss);
|
| -}
|
| -
|
| -
|
| -void PropertyICCompiler::GenerateRuntimeSetProperty(MacroAssembler* masm,
|
| - StrictMode strict_mode) {
|
| - // Return address is on the stack.
|
| - DCHECK(!ebx.is(StoreIC::ReceiverRegister()) &&
|
| - !ebx.is(StoreIC::NameRegister()) && !ebx.is(StoreIC::ValueRegister()));
|
| - __ pop(ebx);
|
| - __ push(StoreIC::ReceiverRegister());
|
| - __ push(StoreIC::NameRegister());
|
| - __ push(StoreIC::ValueRegister());
|
| - __ push(Immediate(Smi::FromInt(strict_mode)));
|
| - __ push(ebx); // return address
|
| -
|
| - // Do tail-call to runtime routine.
|
| - __ TailCallRuntime(Runtime::kSetProperty, 4, 1);
|
| -}
|
| -
|
| -
|
| #undef __
|
| }
|
| } // namespace v8::internal
|
|
|