Home | History | Annotate | Download | only in builtins
      1 // Copyright 2016 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/builtins/builtins-utils.h"
      6 #include "src/builtins/builtins.h"
      7 #include "src/code-stub-assembler.h"
      8 #include "src/ic/handler-compiler.h"
      9 #include "src/ic/ic.h"
     10 #include "src/ic/keyed-store-generic.h"
     11 #include "src/objects-inl.h"
     12 
     13 namespace v8 {
     14 namespace internal {
     15 
     16 TF_BUILTIN(KeyedLoadIC_IndexedString, CodeStubAssembler) {
     17   typedef LoadWithVectorDescriptor Descriptor;
     18 
     19   Node* receiver = Parameter(Descriptor::kReceiver);
     20   Node* index = Parameter(Descriptor::kName);
     21   Node* slot = Parameter(Descriptor::kSlot);
     22   Node* vector = Parameter(Descriptor::kVector);
     23   Node* context = Parameter(Descriptor::kContext);
     24 
     25   Label miss(this);
     26 
     27   Node* index_intptr = TryToIntptr(index, &miss);
     28   Node* length = SmiUntag(LoadStringLength(receiver));
     29   GotoIf(UintPtrGreaterThanOrEqual(index_intptr, length), &miss);
     30 
     31   Node* code = StringCharCodeAt(receiver, index_intptr, INTPTR_PARAMETERS);
     32   Node* result = StringFromCharCode(code);
     33   Return(result);
     34 
     35   Bind(&miss);
     36   TailCallRuntime(Runtime::kKeyedLoadIC_Miss, context, receiver, index, slot,
     37                   vector);
     38 }
     39 
     40 TF_BUILTIN(KeyedLoadIC_Miss, CodeStubAssembler) {
     41   typedef LoadWithVectorDescriptor Descriptor;
     42 
     43   Node* receiver = Parameter(Descriptor::kReceiver);
     44   Node* name = Parameter(Descriptor::kName);
     45   Node* slot = Parameter(Descriptor::kSlot);
     46   Node* vector = Parameter(Descriptor::kVector);
     47   Node* context = Parameter(Descriptor::kContext);
     48 
     49   TailCallRuntime(Runtime::kKeyedLoadIC_Miss, context, receiver, name, slot,
     50                   vector);
     51 }
     52 
     53 TF_BUILTIN(KeyedLoadIC_Slow, CodeStubAssembler) {
     54   typedef LoadWithVectorDescriptor Descriptor;
     55 
     56   Node* receiver = Parameter(Descriptor::kReceiver);
     57   Node* name = Parameter(Descriptor::kName);
     58   Node* context = Parameter(Descriptor::kContext);
     59 
     60   TailCallRuntime(Runtime::kKeyedGetProperty, context, receiver, name);
     61 }
     62 
     63 void Builtins::Generate_KeyedStoreIC_Megamorphic(
     64     compiler::CodeAssemblerState* state) {
     65   KeyedStoreGenericGenerator::Generate(state, SLOPPY);
     66 }
     67 
     68 void Builtins::Generate_KeyedStoreIC_Megamorphic_Strict(
     69     compiler::CodeAssemblerState* state) {
     70   KeyedStoreGenericGenerator::Generate(state, STRICT);
     71 }
     72 
     73 TF_BUILTIN(KeyedStoreIC_Miss, CodeStubAssembler) {
     74   typedef StoreWithVectorDescriptor Descriptor;
     75 
     76   Node* receiver = Parameter(Descriptor::kReceiver);
     77   Node* name = Parameter(Descriptor::kName);
     78   Node* value = Parameter(Descriptor::kValue);
     79   Node* slot = Parameter(Descriptor::kSlot);
     80   Node* vector = Parameter(Descriptor::kVector);
     81   Node* context = Parameter(Descriptor::kContext);
     82 
     83   TailCallRuntime(Runtime::kKeyedStoreIC_Miss, context, value, slot, vector,
     84                   receiver, name);
     85 }
     86 
     87 TF_BUILTIN(KeyedStoreIC_Slow, CodeStubAssembler) {
     88   typedef StoreWithVectorDescriptor Descriptor;
     89 
     90   Node* receiver = Parameter(Descriptor::kReceiver);
     91   Node* name = Parameter(Descriptor::kName);
     92   Node* value = Parameter(Descriptor::kValue);
     93   Node* slot = Parameter(Descriptor::kSlot);
     94   Node* vector = Parameter(Descriptor::kVector);
     95   Node* context = Parameter(Descriptor::kContext);
     96 
     97   // The slow case calls into the runtime to complete the store without causing
     98   // an IC miss that would otherwise cause a transition to the generic stub.
     99   TailCallRuntime(Runtime::kKeyedStoreIC_Slow, context, value, slot, vector,
    100                   receiver, name);
    101 }
    102 
    103 TF_BUILTIN(LoadGlobalIC_Miss, CodeStubAssembler) {
    104   typedef LoadGlobalWithVectorDescriptor Descriptor;
    105 
    106   Node* name = Parameter(Descriptor::kName);
    107   Node* slot = Parameter(Descriptor::kSlot);
    108   Node* vector = Parameter(Descriptor::kVector);
    109   Node* context = Parameter(Descriptor::kContext);
    110 
    111   TailCallRuntime(Runtime::kLoadGlobalIC_Miss, context, name, slot, vector);
    112 }
    113 
    114 TF_BUILTIN(LoadGlobalIC_Slow, CodeStubAssembler) {
    115   typedef LoadGlobalWithVectorDescriptor Descriptor;
    116 
    117   Node* name = Parameter(Descriptor::kName);
    118   Node* slot = Parameter(Descriptor::kSlot);
    119   Node* vector = Parameter(Descriptor::kVector);
    120   Node* context = Parameter(Descriptor::kContext);
    121 
    122   TailCallRuntime(Runtime::kLoadGlobalIC_Slow, context, name, slot, vector);
    123 }
    124 
    125 void Builtins::Generate_LoadIC_Getter_ForDeopt(MacroAssembler* masm) {
    126   NamedLoadHandlerCompiler::GenerateLoadViaGetterForDeopt(masm);
    127 }
    128 
    129 TF_BUILTIN(LoadIC_FunctionPrototype, CodeStubAssembler) {
    130   typedef LoadWithVectorDescriptor Descriptor;
    131 
    132   Node* receiver = Parameter(Descriptor::kReceiver);
    133   Node* name = Parameter(Descriptor::kName);
    134   Node* slot = Parameter(Descriptor::kSlot);
    135   Node* vector = Parameter(Descriptor::kVector);
    136   Node* context = Parameter(Descriptor::kContext);
    137 
    138   Label miss(this);
    139 
    140   Node* proto_or_map =
    141       LoadObjectField(receiver, JSFunction::kPrototypeOrInitialMapOffset);
    142   GotoIf(IsTheHole(proto_or_map), &miss);
    143 
    144   Variable var_result(this, MachineRepresentation::kTagged, proto_or_map);
    145   Label done(this, &var_result);
    146   GotoIfNot(IsMap(proto_or_map), &done);
    147 
    148   var_result.Bind(LoadMapPrototype(proto_or_map));
    149   Goto(&done);
    150 
    151   Bind(&done);
    152   Return(var_result.value());
    153 
    154   Bind(&miss);
    155   TailCallRuntime(Runtime::kLoadIC_Miss, context, receiver, name, slot, vector);
    156 }
    157 
    158 TF_BUILTIN(LoadIC_Miss, CodeStubAssembler) {
    159   typedef LoadWithVectorDescriptor Descriptor;
    160 
    161   Node* receiver = Parameter(Descriptor::kReceiver);
    162   Node* name = Parameter(Descriptor::kName);
    163   Node* slot = Parameter(Descriptor::kSlot);
    164   Node* vector = Parameter(Descriptor::kVector);
    165   Node* context = Parameter(Descriptor::kContext);
    166 
    167   TailCallRuntime(Runtime::kLoadIC_Miss, context, receiver, name, slot, vector);
    168 }
    169 
    170 TF_BUILTIN(LoadIC_Normal, CodeStubAssembler) {
    171   typedef LoadWithVectorDescriptor Descriptor;
    172 
    173   Node* receiver = Parameter(Descriptor::kReceiver);
    174   Node* name = Parameter(Descriptor::kName);
    175   Node* context = Parameter(Descriptor::kContext);
    176 
    177   Label slow(this);
    178   {
    179     Node* properties = LoadProperties(receiver);
    180     Variable var_name_index(this, MachineType::PointerRepresentation());
    181     Label found(this, &var_name_index);
    182     NameDictionaryLookup<NameDictionary>(properties, name, &found,
    183                                          &var_name_index, &slow);
    184     Bind(&found);
    185     {
    186       Variable var_details(this, MachineRepresentation::kWord32);
    187       Variable var_value(this, MachineRepresentation::kTagged);
    188       LoadPropertyFromNameDictionary(properties, var_name_index.value(),
    189                                      &var_details, &var_value);
    190       Node* value = CallGetterIfAccessor(var_value.value(), var_details.value(),
    191                                          context, receiver, &slow);
    192       Return(value);
    193     }
    194   }
    195 
    196   Bind(&slow);
    197   TailCallRuntime(Runtime::kGetProperty, context, receiver, name);
    198 }
    199 
    200 TF_BUILTIN(LoadIC_Slow, CodeStubAssembler) {
    201   typedef LoadWithVectorDescriptor Descriptor;
    202 
    203   Node* receiver = Parameter(Descriptor::kReceiver);
    204   Node* name = Parameter(Descriptor::kName);
    205   Node* context = Parameter(Descriptor::kContext);
    206 
    207   TailCallRuntime(Runtime::kGetProperty, context, receiver, name);
    208 }
    209 
    210 TF_BUILTIN(StoreIC_Miss, CodeStubAssembler) {
    211   typedef StoreWithVectorDescriptor Descriptor;
    212 
    213   Node* receiver = Parameter(Descriptor::kReceiver);
    214   Node* name = Parameter(Descriptor::kName);
    215   Node* value = Parameter(Descriptor::kValue);
    216   Node* slot = Parameter(Descriptor::kSlot);
    217   Node* vector = Parameter(Descriptor::kVector);
    218   Node* context = Parameter(Descriptor::kContext);
    219 
    220   TailCallRuntime(Runtime::kStoreIC_Miss, context, value, slot, vector,
    221                   receiver, name);
    222 }
    223 
    224 TF_BUILTIN(StoreIC_Normal, CodeStubAssembler) {
    225   typedef StoreWithVectorDescriptor Descriptor;
    226 
    227   Node* receiver = Parameter(Descriptor::kReceiver);
    228   Node* name = Parameter(Descriptor::kName);
    229   Node* value = Parameter(Descriptor::kValue);
    230   Node* slot = Parameter(Descriptor::kSlot);
    231   Node* vector = Parameter(Descriptor::kVector);
    232   Node* context = Parameter(Descriptor::kContext);
    233 
    234   Label slow(this);
    235   {
    236     Node* properties = LoadProperties(receiver);
    237     Variable var_name_index(this, MachineType::PointerRepresentation());
    238     Label found(this, &var_name_index);
    239     NameDictionaryLookup<NameDictionary>(properties, name, &found,
    240                                          &var_name_index, &slow);
    241     Bind(&found);
    242     {
    243       Node* details = LoadDetailsByKeyIndex<NameDictionary>(
    244           properties, var_name_index.value());
    245       // Check that the property is a writable data property (no accessor).
    246       const int kTypeAndReadOnlyMask = PropertyDetails::KindField::kMask |
    247                                        PropertyDetails::kAttributesReadOnlyMask;
    248       STATIC_ASSERT(kData == 0);
    249       GotoIf(IsSetWord32(details, kTypeAndReadOnlyMask), &slow);
    250       StoreValueByKeyIndex<NameDictionary>(properties, var_name_index.value(),
    251                                            value);
    252       Return(value);
    253     }
    254   }
    255 
    256   Bind(&slow);
    257   TailCallRuntime(Runtime::kStoreIC_Miss, context, value, slot, vector,
    258                   receiver, name);
    259 }
    260 
    261 void Builtins::Generate_StoreIC_Setter_ForDeopt(MacroAssembler* masm) {
    262   NamedStoreHandlerCompiler::GenerateStoreViaSetterForDeopt(masm);
    263 }
    264 
    265 }  // namespace internal
    266 }  // namespace v8
    267