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 
ComputeKeyedStoreMonomorphicHandler(Handle<Map> receiver_map,KeyedAccessStoreMode store_mode)13 Handle<Code> PropertyICCompiler::ComputeKeyedStoreMonomorphicHandler(
14     Handle<Map> receiver_map, KeyedAccessStoreMode store_mode) {
15   Isolate* isolate = receiver_map->GetIsolate();
16 
17   DCHECK(store_mode == STANDARD_STORE ||
18          store_mode == STORE_AND_GROW_NO_TRANSITION ||
19          store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS ||
20          store_mode == STORE_NO_TRANSITION_HANDLE_COW);
21 
22   PropertyICCompiler compiler(isolate);
23   Handle<Code> code =
24       compiler.CompileKeyedStoreMonomorphicHandler(receiver_map, store_mode);
25   return code;
26 }
27 
ComputeKeyedStorePolymorphicHandlers(MapHandleList * receiver_maps,MapHandleList * transitioned_maps,CodeHandleList * handlers,KeyedAccessStoreMode store_mode)28 void PropertyICCompiler::ComputeKeyedStorePolymorphicHandlers(
29     MapHandleList* receiver_maps, MapHandleList* transitioned_maps,
30     CodeHandleList* handlers, KeyedAccessStoreMode store_mode) {
31   Isolate* isolate = receiver_maps->at(0)->GetIsolate();
32   DCHECK(store_mode == STANDARD_STORE ||
33          store_mode == STORE_AND_GROW_NO_TRANSITION ||
34          store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS ||
35          store_mode == STORE_NO_TRANSITION_HANDLE_COW);
36   PropertyICCompiler compiler(isolate);
37   compiler.CompileKeyedStorePolymorphicHandlers(
38       receiver_maps, transitioned_maps, handlers, store_mode);
39 }
40 
41 
CompileKeyedStorePolymorphicHandlers(MapHandleList * receiver_maps,MapHandleList * transitioned_maps,CodeHandleList * handlers,KeyedAccessStoreMode store_mode)42 void PropertyICCompiler::CompileKeyedStorePolymorphicHandlers(
43     MapHandleList* receiver_maps, MapHandleList* transitioned_maps,
44     CodeHandleList* handlers, KeyedAccessStoreMode store_mode) {
45   for (int i = 0; i < receiver_maps->length(); ++i) {
46     Handle<Map> receiver_map(receiver_maps->at(i));
47     Handle<Code> cached_stub;
48     Handle<Map> transitioned_map;
49     {
50       Map* tmap = receiver_map->FindElementsKindTransitionedMap(receiver_maps);
51       if (tmap != nullptr) transitioned_map = handle(tmap);
52     }
53 
54     // TODO(mvstanton): The code below is doing pessimistic elements
55     // transitions. I would like to stop doing that and rely on Allocation Site
56     // Tracking to do a better job of ensuring the data types are what they need
57     // to be. Not all the elements are in place yet, pessimistic elements
58     // transitions are still important for performance.
59     if (!transitioned_map.is_null()) {
60       bool is_js_array = receiver_map->instance_type() == JS_ARRAY_TYPE;
61       ElementsKind elements_kind = receiver_map->elements_kind();
62       TRACE_HANDLER_STATS(isolate(),
63                           KeyedStoreIC_ElementsTransitionAndStoreStub);
64       cached_stub =
65           ElementsTransitionAndStoreStub(isolate(), elements_kind,
66                                          transitioned_map->elements_kind(),
67                                          is_js_array, store_mode).GetCode();
68     } else if (receiver_map->instance_type() < FIRST_JS_RECEIVER_TYPE) {
69       // TODO(mvstanton): Consider embedding store_mode in the state of the slow
70       // keyed store ic for uniformity.
71       TRACE_HANDLER_STATS(isolate(), KeyedStoreIC_SlowStub);
72       cached_stub = isolate()->builtins()->KeyedStoreIC_Slow();
73     } else {
74       cached_stub =
75           CompileKeyedStoreMonomorphicHandler(receiver_map, store_mode);
76     }
77     DCHECK(!cached_stub.is_null());
78     handlers->Add(cached_stub);
79     transitioned_maps->Add(transitioned_map);
80   }
81 }
82 
83 
84 #define __ ACCESS_MASM(masm())
85 
86 
CompileKeyedStoreMonomorphicHandler(Handle<Map> receiver_map,KeyedAccessStoreMode store_mode)87 Handle<Code> PropertyICCompiler::CompileKeyedStoreMonomorphicHandler(
88     Handle<Map> receiver_map, KeyedAccessStoreMode store_mode) {
89   ElementsKind elements_kind = receiver_map->elements_kind();
90   bool is_jsarray = receiver_map->instance_type() == JS_ARRAY_TYPE;
91   Handle<Code> stub;
92   if (receiver_map->has_sloppy_arguments_elements()) {
93     TRACE_HANDLER_STATS(isolate(), KeyedStoreIC_KeyedStoreSloppyArgumentsStub);
94     stub = KeyedStoreSloppyArgumentsStub(isolate(), store_mode).GetCode();
95   } else if (receiver_map->has_fast_elements() ||
96              receiver_map->has_fixed_typed_array_elements()) {
97     TRACE_HANDLER_STATS(isolate(), KeyedStoreIC_StoreFastElementStub);
98     stub = StoreFastElementStub(isolate(), is_jsarray, elements_kind,
99                                 store_mode).GetCode();
100   } else {
101     TRACE_HANDLER_STATS(isolate(), KeyedStoreIC_StoreElementStub);
102     stub = StoreElementStub(isolate(), elements_kind, store_mode).GetCode();
103   }
104   return stub;
105 }
106 
107 
108 #undef __
109 }  // namespace internal
110 }  // namespace v8
111