blob: 9f1d87ac617247a7a63cde08804ba119b68f1035 [file] [log] [blame]
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001// 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
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00005#include "src/ic/ic-compiler.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +00006
7#include "src/ic/handler-compiler.h"
8#include "src/ic/ic-inl.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00009#include "src/profiler/cpu-profiler.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000010
11
12namespace v8 {
13namespace internal {
14
15
16Handle<Code> PropertyICCompiler::Find(Handle<Name> name,
17 Handle<Map> stub_holder, Code::Kind kind,
18 ExtraICState extra_state,
19 CacheHolderFlag cache_holder) {
20 Code::Flags flags =
21 Code::ComputeMonomorphicFlags(kind, extra_state, cache_holder);
22 Object* probe = stub_holder->FindInCodeCache(*name, flags);
23 if (probe->IsCode()) return handle(Code::cast(probe));
24 return Handle<Code>::null();
25}
26
27
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000028bool PropertyICCompiler::IncludesNumberMap(MapHandleList* maps) {
29 for (int i = 0; i < maps->length(); ++i) {
30 if (maps->at(i)->instance_type() == HEAP_NUMBER_TYPE) return true;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000031 }
32 return false;
33}
34
35
Emily Bernierd0a1eb72015-03-24 16:35:39 -040036Handle<Code> PropertyICCompiler::ComputeKeyedLoadMonomorphicHandler(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000037 Handle<Map> receiver_map, ExtraICState extra_ic_state) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -040038 Isolate* isolate = receiver_map->GetIsolate();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000039 bool is_js_array = receiver_map->instance_type() == JS_ARRAY_TYPE;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000040 ElementsKind elements_kind = receiver_map->elements_kind();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000041
42 // No need to check for an elements-free prototype chain here, the generated
43 // stub code needs to check that dynamically anyway.
44 bool convert_hole_to_undefined =
45 is_js_array && elements_kind == FAST_HOLEY_ELEMENTS &&
Ben Murdoch097c5b22016-05-18 11:27:45 +010046 *receiver_map == isolate->get_initial_js_array_map(elements_kind);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000047 Handle<Code> stub;
48 if (receiver_map->has_indexed_interceptor()) {
49 stub = LoadIndexedInterceptorStub(isolate).GetCode();
Emily Bernierd0a1eb72015-03-24 16:35:39 -040050 } else if (receiver_map->IsStringMap()) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -040051 stub = LoadIndexedStringStub(isolate).GetCode();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000052 } else if (receiver_map->has_sloppy_arguments_elements()) {
53 stub = KeyedLoadSloppyArgumentsStub(isolate).GetCode();
54 } else if (receiver_map->has_fast_elements() ||
Ben Murdochb8a8cc12014-11-26 15:28:44 +000055 receiver_map->has_fixed_typed_array_elements()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000056 stub = LoadFastElementStub(isolate, is_js_array, elements_kind,
57 convert_hole_to_undefined).GetCode();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000058 } else {
Ben Murdoch097c5b22016-05-18 11:27:45 +010059 DCHECK(receiver_map->has_dictionary_elements());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000060 stub = LoadDictionaryElementStub(isolate, LoadICState(extra_ic_state))
61 .GetCode();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000062 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -040063 return stub;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000064}
65
66
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000067Handle<Code> PropertyICCompiler::ComputeKeyedStoreMonomorphicHandler(
68 Handle<Map> receiver_map, LanguageMode language_mode,
Ben Murdochb8a8cc12014-11-26 15:28:44 +000069 KeyedAccessStoreMode store_mode) {
70 Isolate* isolate = receiver_map->GetIsolate();
71 ExtraICState extra_state =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000072 KeyedStoreIC::ComputeExtraICState(language_mode, store_mode);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000073
74 DCHECK(store_mode == STANDARD_STORE ||
75 store_mode == STORE_AND_GROW_NO_TRANSITION ||
76 store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS ||
77 store_mode == STORE_NO_TRANSITION_HANDLE_COW);
78
Ben Murdochb8a8cc12014-11-26 15:28:44 +000079 PropertyICCompiler compiler(isolate, Code::KEYED_STORE_IC, extra_state);
80 Handle<Code> code =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000081 compiler.CompileKeyedStoreMonomorphicHandler(receiver_map, store_mode);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000082 return code;
83}
84
85
86Code* PropertyICCompiler::FindPreMonomorphic(Isolate* isolate, Code::Kind kind,
87 ExtraICState state) {
88 Code::Flags flags = Code::ComputeFlags(kind, PREMONOMORPHIC, state);
89 UnseededNumberDictionary* dictionary =
90 isolate->heap()->non_monomorphic_cache();
91 int entry = dictionary->FindEntry(isolate, flags);
92 DCHECK(entry != -1);
93 Object* code = dictionary->ValueAt(entry);
94 // This might be called during the marking phase of the collector
95 // hence the unchecked cast.
96 return reinterpret_cast<Code*>(code);
97}
98
99
100static void FillCache(Isolate* isolate, Handle<Code> code) {
101 Handle<UnseededNumberDictionary> dictionary = UnseededNumberDictionary::Set(
102 isolate->factory()->non_monomorphic_cache(), code->flags(), code);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000103 isolate->heap()->SetRootNonMonomorphicCache(*dictionary);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000104}
105
106
107Handle<Code> PropertyICCompiler::ComputeStore(Isolate* isolate,
108 InlineCacheState ic_state,
109 ExtraICState extra_state) {
110 Code::Flags flags = Code::ComputeFlags(Code::STORE_IC, ic_state, extra_state);
111 Handle<UnseededNumberDictionary> cache =
112 isolate->factory()->non_monomorphic_cache();
113 int entry = cache->FindEntry(isolate, flags);
114 if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry)));
115
116 PropertyICCompiler compiler(isolate, Code::STORE_IC);
117 Handle<Code> code;
118 if (ic_state == UNINITIALIZED) {
119 code = compiler.CompileStoreInitialize(flags);
120 } else if (ic_state == PREMONOMORPHIC) {
121 code = compiler.CompileStorePreMonomorphic(flags);
122 } else if (ic_state == GENERIC) {
123 code = compiler.CompileStoreGeneric(flags);
124 } else if (ic_state == MEGAMORPHIC) {
125 code = compiler.CompileStoreMegamorphic(flags);
126 } else {
127 UNREACHABLE();
128 }
129
130 FillCache(isolate, code);
131 return code;
132}
133
134
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000135void PropertyICCompiler::ComputeKeyedStorePolymorphicHandlers(
136 MapHandleList* receiver_maps, MapHandleList* transitioned_maps,
137 CodeHandleList* handlers, KeyedAccessStoreMode store_mode,
138 LanguageMode language_mode) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000139 Isolate* isolate = receiver_maps->at(0)->GetIsolate();
140 DCHECK(store_mode == STANDARD_STORE ||
141 store_mode == STORE_AND_GROW_NO_TRANSITION ||
142 store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS ||
143 store_mode == STORE_NO_TRANSITION_HANDLE_COW);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000144 ExtraICState extra_state =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000145 KeyedStoreIC::ComputeExtraICState(language_mode, store_mode);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000146 PropertyICCompiler compiler(isolate, Code::KEYED_STORE_IC, extra_state);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000147 compiler.CompileKeyedStorePolymorphicHandlers(
148 receiver_maps, transitioned_maps, handlers, store_mode);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000149}
150
151
152Handle<Code> PropertyICCompiler::CompileLoadInitialize(Code::Flags flags) {
153 LoadIC::GenerateInitialize(masm());
154 Handle<Code> code = GetCodeWithFlags(flags, "CompileLoadInitialize");
Ben Murdochda12d292016-06-02 14:46:10 +0100155 PROFILE(isolate(), CodeCreateEvent(Logger::LOAD_INITIALIZE_TAG,
156 AbstractCode::cast(*code), 0));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000157 return code;
158}
159
160
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000161Handle<Code> PropertyICCompiler::CompileStoreInitialize(Code::Flags flags) {
162 StoreIC::GenerateInitialize(masm());
163 Handle<Code> code = GetCodeWithFlags(flags, "CompileStoreInitialize");
Ben Murdochda12d292016-06-02 14:46:10 +0100164 PROFILE(isolate(), CodeCreateEvent(Logger::STORE_INITIALIZE_TAG,
165 AbstractCode::cast(*code), 0));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000166 return code;
167}
168
169
170Handle<Code> PropertyICCompiler::CompileStorePreMonomorphic(Code::Flags flags) {
171 StoreIC::GeneratePreMonomorphic(masm());
172 Handle<Code> code = GetCodeWithFlags(flags, "CompileStorePreMonomorphic");
Ben Murdochda12d292016-06-02 14:46:10 +0100173 PROFILE(isolate(), CodeCreateEvent(Logger::STORE_PREMONOMORPHIC_TAG,
174 AbstractCode::cast(*code), 0));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000175 return code;
176}
177
178
179Handle<Code> PropertyICCompiler::CompileStoreGeneric(Code::Flags flags) {
180 ExtraICState extra_state = Code::ExtractExtraICStateFromFlags(flags);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000181 LanguageMode language_mode = StoreICState::GetLanguageMode(extra_state);
182 GenerateRuntimeSetProperty(masm(), language_mode);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000183 Handle<Code> code = GetCodeWithFlags(flags, "CompileStoreGeneric");
Ben Murdochda12d292016-06-02 14:46:10 +0100184 PROFILE(isolate(), CodeCreateEvent(Logger::STORE_GENERIC_TAG,
185 AbstractCode::cast(*code), 0));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000186 return code;
187}
188
189
190Handle<Code> PropertyICCompiler::CompileStoreMegamorphic(Code::Flags flags) {
191 StoreIC::GenerateMegamorphic(masm());
192 Handle<Code> code = GetCodeWithFlags(flags, "CompileStoreMegamorphic");
Ben Murdochda12d292016-06-02 14:46:10 +0100193 PROFILE(isolate(), CodeCreateEvent(Logger::STORE_MEGAMORPHIC_TAG,
194 AbstractCode::cast(*code), 0));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000195 return code;
196}
197
198
199Handle<Code> PropertyICCompiler::GetCode(Code::Kind kind, Code::StubType type,
200 Handle<Name> name,
201 InlineCacheState state) {
202 Code::Flags flags =
203 Code::ComputeFlags(kind, state, extra_ic_state_, type, cache_holder());
204 Handle<Code> code = GetCodeWithFlags(flags, name);
Ben Murdochda12d292016-06-02 14:46:10 +0100205 PROFILE(isolate(),
206 CodeCreateEvent(log_kind(code), AbstractCode::cast(*code), *name));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000207#ifdef DEBUG
208 code->VerifyEmbeddedObjects();
209#endif
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000210 return code;
211}
212
213
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000214void PropertyICCompiler::CompileKeyedStorePolymorphicHandlers(
215 MapHandleList* receiver_maps, MapHandleList* transitioned_maps,
216 CodeHandleList* handlers, KeyedAccessStoreMode store_mode) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000217 for (int i = 0; i < receiver_maps->length(); ++i) {
218 Handle<Map> receiver_map(receiver_maps->at(i));
219 Handle<Code> cached_stub;
220 Handle<Map> transitioned_map =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000221 Map::FindTransitionedMap(receiver_map, receiver_maps);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000222
223 // TODO(mvstanton): The code below is doing pessimistic elements
224 // transitions. I would like to stop doing that and rely on Allocation Site
225 // Tracking to do a better job of ensuring the data types are what they need
226 // to be. Not all the elements are in place yet, pessimistic elements
227 // transitions are still important for performance.
228 bool is_js_array = receiver_map->instance_type() == JS_ARRAY_TYPE;
229 ElementsKind elements_kind = receiver_map->elements_kind();
230 if (!transitioned_map.is_null()) {
231 cached_stub =
232 ElementsTransitionAndStoreStub(isolate(), elements_kind,
233 transitioned_map->elements_kind(),
234 is_js_array, store_mode).GetCode();
235 } else if (receiver_map->instance_type() < FIRST_JS_RECEIVER_TYPE) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000236 // TODO(mvstanton): Consider embedding store_mode in the state of the slow
237 // keyed store ic for uniformity.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000238 cached_stub = isolate()->builtins()->KeyedStoreIC_Slow();
239 } else {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000240 if (IsSloppyArgumentsElements(elements_kind)) {
241 cached_stub =
242 KeyedStoreSloppyArgumentsStub(isolate(), store_mode).GetCode();
243 } else if (receiver_map->has_fast_elements() ||
244 receiver_map->has_fixed_typed_array_elements()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000245 cached_stub = StoreFastElementStub(isolate(), is_js_array,
246 elements_kind, store_mode).GetCode();
247 } else {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000248 cached_stub =
249 StoreElementStub(isolate(), elements_kind, store_mode).GetCode();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000250 }
251 }
252 DCHECK(!cached_stub.is_null());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000253 handlers->Add(cached_stub);
254 transitioned_maps->Add(transitioned_map);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000255 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000256}
257
258
259#define __ ACCESS_MASM(masm())
260
261
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000262Handle<Code> PropertyICCompiler::CompileKeyedStoreMonomorphicHandler(
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000263 Handle<Map> receiver_map, KeyedAccessStoreMode store_mode) {
264 ElementsKind elements_kind = receiver_map->elements_kind();
265 bool is_jsarray = receiver_map->instance_type() == JS_ARRAY_TYPE;
266 Handle<Code> stub;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000267 if (receiver_map->has_sloppy_arguments_elements()) {
268 stub = KeyedStoreSloppyArgumentsStub(isolate(), store_mode).GetCode();
269 } else if (receiver_map->has_fast_elements() ||
270 receiver_map->has_fixed_typed_array_elements()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000271 stub = StoreFastElementStub(isolate(), is_jsarray, elements_kind,
272 store_mode).GetCode();
273 } else {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000274 stub = StoreElementStub(isolate(), elements_kind, store_mode).GetCode();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000275 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000276 return stub;
277}
278
279
280Handle<Code> PropertyICCompiler::CompileKeyedStoreMonomorphic(
281 Handle<Map> receiver_map, KeyedAccessStoreMode store_mode) {
282 Handle<Code> stub =
283 CompileKeyedStoreMonomorphicHandler(receiver_map, store_mode);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000284
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400285 Handle<WeakCell> cell = Map::WeakCellForMap(receiver_map);
286
287 __ DispatchWeakMap(receiver(), scratch1(), scratch2(), cell, stub,
288 DO_SMI_CHECK);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000289
290 TailCallBuiltin(masm(), Builtins::kKeyedStoreIC_Miss);
291
292 return GetCode(kind(), Code::NORMAL, factory()->empty_string());
293}
294
295
296#undef __
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000297} // namespace internal
298} // namespace v8