• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
ComputeKeyedLoadMonomorphicHandler(Handle<Map> receiver_map,ExtraICState extra_ic_state)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 
ComputeKeyedStoreMonomorphicHandler(Handle<Map> receiver_map,KeyedAccessStoreMode store_mode)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 
ComputeKeyedStorePolymorphicHandlers(MapHandleList * receiver_maps,MapHandleList * transitioned_maps,CodeHandleList * handlers,KeyedAccessStoreMode store_mode)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 
CompileKeyedStorePolymorphicHandlers(MapHandleList * receiver_maps,MapHandleList * transitioned_maps,CodeHandleList * handlers,KeyedAccessStoreMode store_mode)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 
CompileKeyedStoreMonomorphicHandler(Handle<Map> receiver_map,KeyedAccessStoreMode store_mode)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