| Index: src/ic/mips/handler-compiler-mips.cc
|
| diff --git a/src/ic/mips/ic-compiler-mips.cc b/src/ic/mips/handler-compiler-mips.cc
|
| similarity index 88%
|
| copy from src/ic/mips/ic-compiler-mips.cc
|
| copy to src/ic/mips/handler-compiler-mips.cc
|
| index fa52cd8e83d2de27328dc295a4c7c2eab7b18ad1..b6aa4821df59498a6ae140639435d41201978209 100644
|
| --- a/src/ic/mips/ic-compiler-mips.cc
|
| +++ b/src/ic/mips/handler-compiler-mips.cc
|
| @@ -7,7 +7,7 @@
|
| #if V8_TARGET_ARCH_MIPS
|
|
|
| #include "src/ic/call-optimization.h"
|
| -#include "src/ic/ic-compiler.h"
|
| +#include "src/ic/handler-compiler.h"
|
|
|
| namespace v8 {
|
| namespace internal {
|
| @@ -15,6 +15,82 @@ namespace internal {
|
| #define __ ACCESS_MASM(masm)
|
|
|
|
|
| +void NamedLoadHandlerCompiler::GenerateLoadViaGetter(
|
| + MacroAssembler* masm, Handle<HeapType> type, Register receiver,
|
| + Handle<JSFunction> getter) {
|
| + // ----------- S t a t e -------------
|
| + // -- a0 : receiver
|
| + // -- a2 : name
|
| + // -- ra : 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.
|
| + __ lw(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.
|
| + __ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
|
| + }
|
| + __ Ret();
|
| +}
|
| +
|
| +
|
| +void NamedStoreHandlerCompiler::GenerateStoreViaSetter(
|
| + MacroAssembler* masm, Handle<HeapType> type, Register receiver,
|
| + Handle<JSFunction> setter) {
|
| + // ----------- S t a t e -------------
|
| + // -- ra : 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.
|
| + __ lw(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(v0);
|
| +
|
| + // Restore context register.
|
| + __ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
|
| + }
|
| + __ Ret();
|
| +}
|
| +
|
| +
|
| void PropertyHandlerCompiler::GenerateDictionaryNegativeLookup(
|
| MacroAssembler* masm, Label* miss_label, Register receiver,
|
| Handle<Name> name, Register scratch0, Register scratch1) {
|
| @@ -27,7 +103,7 @@ void PropertyHandlerCompiler::GenerateDictionaryNegativeLookup(
|
| Label done;
|
|
|
| const int kInterceptorOrAccessCheckNeededMask =
|
| - (1 << Map::kHasNamedInterceptor) | (1 << Map::kIsAccessCheckNeeded);
|
| + (1 << Map::kHasNamedInterceptor) | (1 << Map::kIsAccessCheckNeeded);
|
|
|
| // Bail out if the receiver has a named interceptor or requires access checks.
|
| Register map = scratch1;
|
| @@ -92,6 +168,9 @@ void NamedLoadHandlerCompiler::GenerateLoadFunctionPrototype(
|
| }
|
|
|
|
|
| +// Generate code to check that a global property cell is empty. Create
|
| +// the property cell at compilation time if no cell exists for the
|
| +// property.
|
| void PropertyHandlerCompiler::GenerateCheckPropertyCell(
|
| MacroAssembler* masm, Handle<JSGlobalObject> global, Handle<Name> name,
|
| Register scratch, Label* miss) {
|
| @@ -202,6 +281,35 @@ void PropertyHandlerCompiler::GenerateFastApiCall(
|
| }
|
|
|
|
|
| +void ElementHandlerCompiler::GenerateLoadDictionaryElement(
|
| + MacroAssembler* masm) {
|
| + // The return address is in ra.
|
| + Label slow, miss;
|
| +
|
| + Register key = LoadIC::NameRegister();
|
| + Register receiver = LoadIC::ReceiverRegister();
|
| + DCHECK(receiver.is(a1));
|
| + DCHECK(key.is(a2));
|
| +
|
| + __ UntagAndJumpIfNotSmi(t2, key, &miss);
|
| + __ lw(t0, FieldMemOperand(receiver, JSObject::kElementsOffset));
|
| + __ LoadFromNumberDictionary(&slow, t0, key, v0, t2, a3, t1);
|
| + __ Ret();
|
| +
|
| + // Slow case, key and receiver still unmodified.
|
| + __ bind(&slow);
|
| + __ IncrementCounter(
|
| + masm->isolate()->counters()->keyed_load_external_array_slow(), 1, a2, a3);
|
| +
|
| + TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Slow);
|
| +
|
| + // Miss case, call the runtime.
|
| + __ bind(&miss);
|
| +
|
| + TailCallBuiltin(masm, Builtins::kKeyedLoadIC_Miss);
|
| +}
|
| +
|
| +
|
| #undef __
|
| #define __ ACCESS_MASM(masm())
|
|
|
| @@ -680,54 +788,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 -------------
|
| - // -- ra : 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.
|
| - __ lw(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(v0);
|
| -
|
| - // Restore context register.
|
| - __ lw(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
|
| - }
|
| - __ Ret();
|
| -}
|
| -
|
| -
|
| -#undef __
|
| -#define __ ACCESS_MASM(masm())
|
| -
|
| -
|
| Handle<Code> NamedStoreHandlerCompiler::CompileStoreInterceptor(
|
| Handle<Name> name) {
|
| __ Push(receiver(), this->name(), value());
|
| @@ -745,50 +805,6 @@ Handle<Code> NamedStoreHandlerCompiler::CompileStoreInterceptor(
|
| 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 -------------
|
| - // -- a0 : receiver
|
| - // -- a2 : name
|
| - // -- ra : 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.
|
| - __ lw(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.
|
| - __ lw(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;
|
| @@ -818,140 +834,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 {
|
| - __ Branch(&miss, ne, this->name(), Operand(name));
|
| - }
|
| - }
|
| -
|
| - Label number_case;
|
| - Register match = scratch2();
|
| - Label* smi_target = IncludesNumberType(types) ? &number_case : &miss;
|
| - __ JumpIfSmi(receiver(), smi_target, match); // Reg match is 0 if Smi.
|
| -
|
| - // Polymorphic keyed stores may use the map register
|
| - Register map_reg = scratch1();
|
| - DCHECK(kind() != Code::KEYED_STORE_IC ||
|
| - map_reg.is(KeyedStoreIC::MapRegister()));
|
| -
|
| - int receiver_count = types->length();
|
| - int number_of_handled_maps = 0;
|
| - __ lw(map_reg, FieldMemOperand(receiver(), HeapObject::kMapOffset));
|
| - 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.
|
| - // Separate compare from branch, to provide path for above JumpIfSmi().
|
| - __ Subu(match, map_reg, Operand(map));
|
| - if (type->Is(HeapType::Number())) {
|
| - DCHECK(!number_case.is_unused());
|
| - __ bind(&number_case);
|
| - }
|
| - __ Jump(handlers->at(current), RelocInfo::CODE_TARGET, eq, match,
|
| - Operand(zero_reg));
|
| - }
|
| - }
|
| - 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;
|
| - __ JumpIfSmi(receiver(), &miss);
|
| -
|
| - int receiver_count = receiver_maps->length();
|
| - __ lw(scratch1(), FieldMemOperand(receiver(), HeapObject::kMapOffset));
|
| - for (int i = 0; i < receiver_count; ++i) {
|
| - if (transitioned_maps->at(i).is_null()) {
|
| - __ Jump(handler_stubs->at(i), RelocInfo::CODE_TARGET, eq, scratch1(),
|
| - Operand(receiver_maps->at(i)));
|
| - } else {
|
| - Label next_map;
|
| - __ Branch(&next_map, ne, scratch1(), Operand(receiver_maps->at(i)));
|
| - __ li(transition_map(), Operand(transitioned_maps->at(i)));
|
| - __ Jump(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);
|
| -}
|
| -
|
| -
|
| -#undef __
|
| -#define __ ACCESS_MASM(masm)
|
| -
|
| -
|
| -void ElementHandlerCompiler::GenerateLoadDictionaryElement(
|
| - MacroAssembler* masm) {
|
| - // The return address is in ra.
|
| - Label slow, miss;
|
| -
|
| - Register key = LoadIC::NameRegister();
|
| - Register receiver = LoadIC::ReceiverRegister();
|
| - DCHECK(receiver.is(a1));
|
| - DCHECK(key.is(a2));
|
| -
|
| - __ UntagAndJumpIfNotSmi(t2, key, &miss);
|
| - __ lw(t0, FieldMemOperand(receiver, JSObject::kElementsOffset));
|
| - __ LoadFromNumberDictionary(&slow, t0, key, v0, t2, a3, t1);
|
| - __ Ret();
|
| -
|
| - // Slow case, key and receiver still unmodified.
|
| - __ bind(&slow);
|
| - __ IncrementCounter(
|
| - masm->isolate()->counters()->keyed_load_external_array_slow(), 1, a2, a3);
|
| -
|
| - 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) {
|
| - __ Push(StoreIC::ReceiverRegister(), StoreIC::NameRegister(),
|
| - StoreIC::ValueRegister());
|
| -
|
| - __ li(a0, Operand(Smi::FromInt(strict_mode)));
|
| - __ Push(a0);
|
| -
|
| - // Do tail-call to runtime routine.
|
| - __ TailCallRuntime(Runtime::kSetProperty, 4, 1);
|
| -}
|
| -
|
| -
|
| #undef __
|
| }
|
| } // namespace v8::internal
|
|
|