blob: f74c69e50d431ab75a449059c7a776ecf5fb396d [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
135Handle<Code> PropertyICCompiler::ComputeCompareNil(Handle<Map> receiver_map,
136 CompareNilICStub* stub) {
137 Isolate* isolate = receiver_map->GetIsolate();
138 Handle<String> name(isolate->heap()->empty_string());
139 if (!receiver_map->is_dictionary_map()) {
140 Handle<Code> cached_ic =
141 Find(name, receiver_map, Code::COMPARE_NIL_IC, stub->GetExtraICState());
142 if (!cached_ic.is_null()) return cached_ic;
143 }
144
145 Code::FindAndReplacePattern pattern;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400146 Handle<WeakCell> cell = Map::WeakCellForMap(receiver_map);
147 pattern.Add(isolate->factory()->meta_map(), cell);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000148 Handle<Code> ic = stub->GetCodeCopy(pattern);
149
150 if (!receiver_map->is_dictionary_map()) {
151 Map::UpdateCodeCache(receiver_map, name, ic);
152 }
153
154 return ic;
155}
156
157
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000158void PropertyICCompiler::ComputeKeyedStorePolymorphicHandlers(
159 MapHandleList* receiver_maps, MapHandleList* transitioned_maps,
160 CodeHandleList* handlers, KeyedAccessStoreMode store_mode,
161 LanguageMode language_mode) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000162 Isolate* isolate = receiver_maps->at(0)->GetIsolate();
163 DCHECK(store_mode == STANDARD_STORE ||
164 store_mode == STORE_AND_GROW_NO_TRANSITION ||
165 store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS ||
166 store_mode == STORE_NO_TRANSITION_HANDLE_COW);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000167 ExtraICState extra_state =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000168 KeyedStoreIC::ComputeExtraICState(language_mode, store_mode);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000169 PropertyICCompiler compiler(isolate, Code::KEYED_STORE_IC, extra_state);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000170 compiler.CompileKeyedStorePolymorphicHandlers(
171 receiver_maps, transitioned_maps, handlers, store_mode);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000172}
173
174
175Handle<Code> PropertyICCompiler::CompileLoadInitialize(Code::Flags flags) {
176 LoadIC::GenerateInitialize(masm());
177 Handle<Code> code = GetCodeWithFlags(flags, "CompileLoadInitialize");
178 PROFILE(isolate(), CodeCreateEvent(Logger::LOAD_INITIALIZE_TAG, *code, 0));
179 return code;
180}
181
182
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000183Handle<Code> PropertyICCompiler::CompileStoreInitialize(Code::Flags flags) {
184 StoreIC::GenerateInitialize(masm());
185 Handle<Code> code = GetCodeWithFlags(flags, "CompileStoreInitialize");
186 PROFILE(isolate(), CodeCreateEvent(Logger::STORE_INITIALIZE_TAG, *code, 0));
187 return code;
188}
189
190
191Handle<Code> PropertyICCompiler::CompileStorePreMonomorphic(Code::Flags flags) {
192 StoreIC::GeneratePreMonomorphic(masm());
193 Handle<Code> code = GetCodeWithFlags(flags, "CompileStorePreMonomorphic");
194 PROFILE(isolate(),
195 CodeCreateEvent(Logger::STORE_PREMONOMORPHIC_TAG, *code, 0));
196 return code;
197}
198
199
200Handle<Code> PropertyICCompiler::CompileStoreGeneric(Code::Flags flags) {
201 ExtraICState extra_state = Code::ExtractExtraICStateFromFlags(flags);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000202 LanguageMode language_mode = StoreICState::GetLanguageMode(extra_state);
203 GenerateRuntimeSetProperty(masm(), language_mode);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000204 Handle<Code> code = GetCodeWithFlags(flags, "CompileStoreGeneric");
205 PROFILE(isolate(), CodeCreateEvent(Logger::STORE_GENERIC_TAG, *code, 0));
206 return code;
207}
208
209
210Handle<Code> PropertyICCompiler::CompileStoreMegamorphic(Code::Flags flags) {
211 StoreIC::GenerateMegamorphic(masm());
212 Handle<Code> code = GetCodeWithFlags(flags, "CompileStoreMegamorphic");
213 PROFILE(isolate(), CodeCreateEvent(Logger::STORE_MEGAMORPHIC_TAG, *code, 0));
214 return code;
215}
216
217
218Handle<Code> PropertyICCompiler::GetCode(Code::Kind kind, Code::StubType type,
219 Handle<Name> name,
220 InlineCacheState state) {
221 Code::Flags flags =
222 Code::ComputeFlags(kind, state, extra_ic_state_, type, cache_holder());
223 Handle<Code> code = GetCodeWithFlags(flags, name);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000224 PROFILE(isolate(), CodeCreateEvent(log_kind(code), *code, *name));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000225#ifdef DEBUG
226 code->VerifyEmbeddedObjects();
227#endif
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000228 return code;
229}
230
231
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000232void PropertyICCompiler::CompileKeyedStorePolymorphicHandlers(
233 MapHandleList* receiver_maps, MapHandleList* transitioned_maps,
234 CodeHandleList* handlers, KeyedAccessStoreMode store_mode) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000235 for (int i = 0; i < receiver_maps->length(); ++i) {
236 Handle<Map> receiver_map(receiver_maps->at(i));
237 Handle<Code> cached_stub;
238 Handle<Map> transitioned_map =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000239 Map::FindTransitionedMap(receiver_map, receiver_maps);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000240
241 // TODO(mvstanton): The code below is doing pessimistic elements
242 // transitions. I would like to stop doing that and rely on Allocation Site
243 // Tracking to do a better job of ensuring the data types are what they need
244 // to be. Not all the elements are in place yet, pessimistic elements
245 // transitions are still important for performance.
246 bool is_js_array = receiver_map->instance_type() == JS_ARRAY_TYPE;
247 ElementsKind elements_kind = receiver_map->elements_kind();
248 if (!transitioned_map.is_null()) {
249 cached_stub =
250 ElementsTransitionAndStoreStub(isolate(), elements_kind,
251 transitioned_map->elements_kind(),
252 is_js_array, store_mode).GetCode();
253 } else if (receiver_map->instance_type() < FIRST_JS_RECEIVER_TYPE) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000254 // TODO(mvstanton): Consider embedding store_mode in the state of the slow
255 // keyed store ic for uniformity.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000256 cached_stub = isolate()->builtins()->KeyedStoreIC_Slow();
257 } else {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000258 if (IsSloppyArgumentsElements(elements_kind)) {
259 cached_stub =
260 KeyedStoreSloppyArgumentsStub(isolate(), store_mode).GetCode();
261 } else if (receiver_map->has_fast_elements() ||
262 receiver_map->has_fixed_typed_array_elements()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000263 cached_stub = StoreFastElementStub(isolate(), is_js_array,
264 elements_kind, store_mode).GetCode();
265 } else {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000266 cached_stub =
267 StoreElementStub(isolate(), elements_kind, store_mode).GetCode();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000268 }
269 }
270 DCHECK(!cached_stub.is_null());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000271 handlers->Add(cached_stub);
272 transitioned_maps->Add(transitioned_map);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000273 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000274}
275
276
277#define __ ACCESS_MASM(masm())
278
279
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000280Handle<Code> PropertyICCompiler::CompileKeyedStoreMonomorphicHandler(
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000281 Handle<Map> receiver_map, KeyedAccessStoreMode store_mode) {
282 ElementsKind elements_kind = receiver_map->elements_kind();
283 bool is_jsarray = receiver_map->instance_type() == JS_ARRAY_TYPE;
284 Handle<Code> stub;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000285 if (receiver_map->has_sloppy_arguments_elements()) {
286 stub = KeyedStoreSloppyArgumentsStub(isolate(), store_mode).GetCode();
287 } else if (receiver_map->has_fast_elements() ||
288 receiver_map->has_fixed_typed_array_elements()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000289 stub = StoreFastElementStub(isolate(), is_jsarray, elements_kind,
290 store_mode).GetCode();
291 } else {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000292 stub = StoreElementStub(isolate(), elements_kind, store_mode).GetCode();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000293 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000294 return stub;
295}
296
297
298Handle<Code> PropertyICCompiler::CompileKeyedStoreMonomorphic(
299 Handle<Map> receiver_map, KeyedAccessStoreMode store_mode) {
300 Handle<Code> stub =
301 CompileKeyedStoreMonomorphicHandler(receiver_map, store_mode);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000302
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400303 Handle<WeakCell> cell = Map::WeakCellForMap(receiver_map);
304
305 __ DispatchWeakMap(receiver(), scratch1(), scratch2(), cell, stub,
306 DO_SMI_CHECK);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000307
308 TailCallBuiltin(masm(), Builtins::kKeyedStoreIC_Miss);
309
310 return GetCode(kind(), Code::NORMAL, factory()->empty_string());
311}
312
313
314#undef __
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000315} // namespace internal
316} // namespace v8