Home | History | Annotate | Download | only in ic
      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/ic/ic-compiler.h"
      6 
      7 #include "src/ic/handler-compiler.h"
      8 #include "src/ic/ic-inl.h"
      9 
     10 namespace v8 {
     11 namespace internal {
     12 
     13 
     14 Handle<Code> PropertyICCompiler::ComputeKeyedLoadMonomorphicHandler(
     15     Handle<Map> receiver_map, ExtraICState extra_ic_state) {
     16   // TODO(ishell): remove extra_ic_state
     17   Isolate* isolate = receiver_map->GetIsolate();
     18   bool is_js_array = receiver_map->instance_type() == JS_ARRAY_TYPE;
     19   ElementsKind elements_kind = receiver_map->elements_kind();
     20 
     21   // No need to check for an elements-free prototype chain here, the generated
     22   // stub code needs to check that dynamically anyway.
     23   bool convert_hole_to_undefined =
     24       is_js_array && elements_kind == FAST_HOLEY_ELEMENTS &&
     25       *receiver_map == isolate->get_initial_js_array_map(elements_kind);
     26   Handle<Code> stub;
     27   if (receiver_map->has_indexed_interceptor()) {
     28     TRACE_HANDLER_STATS(isolate, KeyedLoadIC_LoadIndexedInterceptorStub);
     29     stub = LoadIndexedInterceptorStub(isolate).GetCode();
     30   } else if (receiver_map->IsStringMap()) {
     31     TRACE_HANDLER_STATS(isolate, KeyedLoadIC_LoadIndexedStringStub);
     32     stub = LoadIndexedStringStub(isolate).GetCode();
     33   } else if (receiver_map->has_sloppy_arguments_elements()) {
     34     TRACE_HANDLER_STATS(isolate, KeyedLoadIC_KeyedLoadSloppyArgumentsStub);
     35     stub = KeyedLoadSloppyArgumentsStub(isolate).GetCode();
     36   } else if (receiver_map->has_fast_elements() ||
     37              receiver_map->has_fixed_typed_array_elements()) {
     38     TRACE_HANDLER_STATS(isolate, KeyedLoadIC_LoadFastElementStub);
     39     stub = LoadFastElementStub(isolate, is_js_array, elements_kind,
     40                                convert_hole_to_undefined).GetCode();
     41   } else {
     42     DCHECK(receiver_map->has_dictionary_elements());
     43     TRACE_HANDLER_STATS(isolate, KeyedLoadIC_LoadDictionaryElementStub);
     44     stub = LoadDictionaryElementStub(isolate).GetCode();
     45   }
     46   return stub;
     47 }
     48 
     49 Handle<Code> PropertyICCompiler::ComputeKeyedStoreMonomorphicHandler(
     50     Handle<Map> receiver_map, KeyedAccessStoreMode store_mode) {
     51   Isolate* isolate = receiver_map->GetIsolate();
     52 
     53   DCHECK(store_mode == STANDARD_STORE ||
     54          store_mode == STORE_AND_GROW_NO_TRANSITION ||
     55          store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS ||
     56          store_mode == STORE_NO_TRANSITION_HANDLE_COW);
     57 
     58   PropertyICCompiler compiler(isolate);
     59   Handle<Code> code =
     60       compiler.CompileKeyedStoreMonomorphicHandler(receiver_map, store_mode);
     61   return code;
     62 }
     63 
     64 void PropertyICCompiler::ComputeKeyedStorePolymorphicHandlers(
     65     MapHandleList* receiver_maps, MapHandleList* transitioned_maps,
     66     CodeHandleList* handlers, KeyedAccessStoreMode store_mode) {
     67   Isolate* isolate = receiver_maps->at(0)->GetIsolate();
     68   DCHECK(store_mode == STANDARD_STORE ||
     69          store_mode == STORE_AND_GROW_NO_TRANSITION ||
     70          store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS ||
     71          store_mode == STORE_NO_TRANSITION_HANDLE_COW);
     72   PropertyICCompiler compiler(isolate);
     73   compiler.CompileKeyedStorePolymorphicHandlers(
     74       receiver_maps, transitioned_maps, handlers, store_mode);
     75 }
     76 
     77 
     78 void PropertyICCompiler::CompileKeyedStorePolymorphicHandlers(
     79     MapHandleList* receiver_maps, MapHandleList* transitioned_maps,
     80     CodeHandleList* handlers, KeyedAccessStoreMode store_mode) {
     81   for (int i = 0; i < receiver_maps->length(); ++i) {
     82     Handle<Map> receiver_map(receiver_maps->at(i));
     83     Handle<Code> cached_stub;
     84     Handle<Map> transitioned_map;
     85     {
     86       Map* tmap = receiver_map->FindElementsKindTransitionedMap(receiver_maps);
     87       if (tmap != nullptr) transitioned_map = handle(tmap);
     88     }
     89 
     90     // TODO(mvstanton): The code below is doing pessimistic elements
     91     // transitions. I would like to stop doing that and rely on Allocation Site
     92     // Tracking to do a better job of ensuring the data types are what they need
     93     // to be. Not all the elements are in place yet, pessimistic elements
     94     // transitions are still important for performance.
     95     bool is_js_array = receiver_map->instance_type() == JS_ARRAY_TYPE;
     96     ElementsKind elements_kind = receiver_map->elements_kind();
     97     if (!transitioned_map.is_null()) {
     98       cached_stub =
     99           ElementsTransitionAndStoreStub(isolate(), elements_kind,
    100                                          transitioned_map->elements_kind(),
    101                                          is_js_array, store_mode).GetCode();
    102     } else if (receiver_map->instance_type() < FIRST_JS_RECEIVER_TYPE) {
    103       // TODO(mvstanton): Consider embedding store_mode in the state of the slow
    104       // keyed store ic for uniformity.
    105       cached_stub = isolate()->builtins()->KeyedStoreIC_Slow();
    106     } else {
    107       if (IsSloppyArgumentsElements(elements_kind)) {
    108         cached_stub =
    109             KeyedStoreSloppyArgumentsStub(isolate(), store_mode).GetCode();
    110       } else if (receiver_map->has_fast_elements() ||
    111                  receiver_map->has_fixed_typed_array_elements()) {
    112         cached_stub = StoreFastElementStub(isolate(), is_js_array,
    113                                            elements_kind, store_mode).GetCode();
    114       } else {
    115         cached_stub =
    116             StoreElementStub(isolate(), elements_kind, store_mode).GetCode();
    117       }
    118     }
    119     DCHECK(!cached_stub.is_null());
    120     handlers->Add(cached_stub);
    121     transitioned_maps->Add(transitioned_map);
    122   }
    123 }
    124 
    125 
    126 #define __ ACCESS_MASM(masm())
    127 
    128 
    129 Handle<Code> PropertyICCompiler::CompileKeyedStoreMonomorphicHandler(
    130     Handle<Map> receiver_map, KeyedAccessStoreMode store_mode) {
    131   ElementsKind elements_kind = receiver_map->elements_kind();
    132   bool is_jsarray = receiver_map->instance_type() == JS_ARRAY_TYPE;
    133   Handle<Code> stub;
    134   if (receiver_map->has_sloppy_arguments_elements()) {
    135     TRACE_HANDLER_STATS(isolate(), KeyedStoreIC_KeyedStoreSloppyArgumentsStub);
    136     stub = KeyedStoreSloppyArgumentsStub(isolate(), store_mode).GetCode();
    137   } else if (receiver_map->has_fast_elements() ||
    138              receiver_map->has_fixed_typed_array_elements()) {
    139     TRACE_HANDLER_STATS(isolate(), KeyedStoreIC_StoreFastElementStub);
    140     stub = StoreFastElementStub(isolate(), is_jsarray, elements_kind,
    141                                 store_mode).GetCode();
    142   } else {
    143     TRACE_HANDLER_STATS(isolate(), KeyedStoreIC_StoreElementStub);
    144     stub = StoreElementStub(isolate(), elements_kind, store_mode).GetCode();
    145   }
    146   return stub;
    147 }
    148 
    149 
    150 #undef __
    151 }  // namespace internal
    152 }  // namespace v8
    153