Home | History | Annotate | Download | only in mips64
      1 // Copyright 2014 the V8 project authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "src/v8.h"
      6 
      7 #if V8_TARGET_ARCH_MIPS64
      8 
      9 #include "src/ic/ic.h"
     10 #include "src/ic/ic-compiler.h"
     11 
     12 namespace v8 {
     13 namespace internal {
     14 
     15 #define __ ACCESS_MASM(masm())
     16 
     17 
     18 Handle<Code> PropertyICCompiler::CompilePolymorphic(TypeHandleList* types,
     19                                                     CodeHandleList* handlers,
     20                                                     Handle<Name> name,
     21                                                     Code::StubType type,
     22                                                     IcCheckType check) {
     23   Label miss;
     24 
     25   if (check == PROPERTY &&
     26       (kind() == Code::KEYED_LOAD_IC || kind() == Code::KEYED_STORE_IC)) {
     27     // In case we are compiling an IC for dictionary loads and stores, just
     28     // check whether the name is unique.
     29     if (name.is_identical_to(isolate()->factory()->normal_ic_symbol())) {
     30       Register tmp = scratch1();
     31       __ JumpIfSmi(this->name(), &miss);
     32       __ ld(tmp, FieldMemOperand(this->name(), HeapObject::kMapOffset));
     33       __ lbu(tmp, FieldMemOperand(tmp, Map::kInstanceTypeOffset));
     34       __ JumpIfNotUniqueNameInstanceType(tmp, &miss);
     35     } else {
     36       __ Branch(&miss, ne, this->name(), Operand(name));
     37     }
     38   }
     39 
     40   Label number_case;
     41   Register match = scratch2();
     42   Label* smi_target = IncludesNumberType(types) ? &number_case : &miss;
     43   __ JumpIfSmi(receiver(), smi_target, match);  // Reg match is 0 if Smi.
     44 
     45   // Polymorphic keyed stores may use the map register
     46   Register map_reg = scratch1();
     47   DCHECK(kind() != Code::KEYED_STORE_IC ||
     48          map_reg.is(ElementTransitionAndStoreDescriptor::MapRegister()));
     49 
     50   int receiver_count = types->length();
     51   int number_of_handled_maps = 0;
     52   __ ld(map_reg, FieldMemOperand(receiver(), HeapObject::kMapOffset));
     53   for (int current = 0; current < receiver_count; ++current) {
     54     Handle<HeapType> type = types->at(current);
     55     Handle<Map> map = IC::TypeToMap(*type, isolate());
     56     if (!map->is_deprecated()) {
     57       number_of_handled_maps++;
     58       // Check map and tail call if there's a match.
     59       // Separate compare from branch, to provide path for above JumpIfSmi().
     60       __ Dsubu(match, map_reg, Operand(map));
     61       if (type->Is(HeapType::Number())) {
     62         DCHECK(!number_case.is_unused());
     63         __ bind(&number_case);
     64       }
     65       __ Jump(handlers->at(current), RelocInfo::CODE_TARGET, eq, match,
     66               Operand(zero_reg));
     67     }
     68   }
     69   DCHECK(number_of_handled_maps != 0);
     70 
     71   __ bind(&miss);
     72   TailCallBuiltin(masm(), MissBuiltin(kind()));
     73 
     74   // Return the generated code.
     75   InlineCacheState state =
     76       number_of_handled_maps > 1 ? POLYMORPHIC : MONOMORPHIC;
     77   return GetCode(kind(), type, name, state);
     78 }
     79 
     80 
     81 Handle<Code> PropertyICCompiler::CompileKeyedStorePolymorphic(
     82     MapHandleList* receiver_maps, CodeHandleList* handler_stubs,
     83     MapHandleList* transitioned_maps) {
     84   Label miss;
     85   __ JumpIfSmi(receiver(), &miss);
     86 
     87   int receiver_count = receiver_maps->length();
     88   __ ld(scratch1(), FieldMemOperand(receiver(), HeapObject::kMapOffset));
     89   for (int i = 0; i < receiver_count; ++i) {
     90     if (transitioned_maps->at(i).is_null()) {
     91       __ Jump(handler_stubs->at(i), RelocInfo::CODE_TARGET, eq, scratch1(),
     92               Operand(receiver_maps->at(i)));
     93     } else {
     94       Label next_map;
     95       __ Branch(&next_map, ne, scratch1(), Operand(receiver_maps->at(i)));
     96       __ li(transition_map(), Operand(transitioned_maps->at(i)));
     97       __ Jump(handler_stubs->at(i), RelocInfo::CODE_TARGET);
     98       __ bind(&next_map);
     99     }
    100   }
    101 
    102   __ bind(&miss);
    103   TailCallBuiltin(masm(), MissBuiltin(kind()));
    104 
    105   // Return the generated code.
    106   return GetCode(kind(), Code::NORMAL, factory()->empty_string(), POLYMORPHIC);
    107 }
    108 
    109 
    110 #undef __
    111 #define __ ACCESS_MASM(masm)
    112 
    113 
    114 void PropertyICCompiler::GenerateRuntimeSetProperty(MacroAssembler* masm,
    115                                                     StrictMode strict_mode) {
    116   __ Push(StoreDescriptor::ReceiverRegister(), StoreDescriptor::NameRegister(),
    117           StoreDescriptor::ValueRegister());
    118 
    119   __ li(a0, Operand(Smi::FromInt(strict_mode)));
    120   __ Push(a0);
    121 
    122   // Do tail-call to runtime routine.
    123   __ TailCallRuntime(Runtime::kSetProperty, 4, 1);
    124 }
    125 
    126 
    127 #undef __
    128 }
    129 }  // namespace v8::internal
    130 
    131 #endif  // V8_TARGET_ARCH_MIPS64
    132