blob: ae4b2a5d58c9ab80e4793adee894de68a8659624 [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 &&
46 *receiver_map == isolate->get_initial_js_array_map(elements_kind) &&
47 !(is_strong(LoadICState::GetLanguageMode(extra_ic_state)));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000048 Handle<Code> stub;
49 if (receiver_map->has_indexed_interceptor()) {
50 stub = LoadIndexedInterceptorStub(isolate).GetCode();
Emily Bernierd0a1eb72015-03-24 16:35:39 -040051 } else if (receiver_map->IsStringMap()) {
52 // We have a string.
53 stub = LoadIndexedStringStub(isolate).GetCode();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000054 } else if (receiver_map->has_sloppy_arguments_elements()) {
55 stub = KeyedLoadSloppyArgumentsStub(isolate).GetCode();
56 } else if (receiver_map->has_fast_elements() ||
Ben Murdochb8a8cc12014-11-26 15:28:44 +000057 receiver_map->has_fixed_typed_array_elements()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000058 stub = LoadFastElementStub(isolate, is_js_array, elements_kind,
59 convert_hole_to_undefined).GetCode();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000060 } else {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000061 stub = LoadDictionaryElementStub(isolate, LoadICState(extra_ic_state))
62 .GetCode();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000063 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -040064 return stub;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000065}
66
67
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000068Handle<Code> PropertyICCompiler::ComputeKeyedStoreMonomorphicHandler(
69 Handle<Map> receiver_map, LanguageMode language_mode,
Ben Murdochb8a8cc12014-11-26 15:28:44 +000070 KeyedAccessStoreMode store_mode) {
71 Isolate* isolate = receiver_map->GetIsolate();
72 ExtraICState extra_state =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000073 KeyedStoreIC::ComputeExtraICState(language_mode, store_mode);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000074
75 DCHECK(store_mode == STANDARD_STORE ||
76 store_mode == STORE_AND_GROW_NO_TRANSITION ||
77 store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS ||
78 store_mode == STORE_NO_TRANSITION_HANDLE_COW);
79
Ben Murdochb8a8cc12014-11-26 15:28:44 +000080 PropertyICCompiler compiler(isolate, Code::KEYED_STORE_IC, extra_state);
81 Handle<Code> code =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000082 compiler.CompileKeyedStoreMonomorphicHandler(receiver_map, store_mode);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000083 return code;
84}
85
86
87Code* PropertyICCompiler::FindPreMonomorphic(Isolate* isolate, Code::Kind kind,
88 ExtraICState state) {
89 Code::Flags flags = Code::ComputeFlags(kind, PREMONOMORPHIC, state);
90 UnseededNumberDictionary* dictionary =
91 isolate->heap()->non_monomorphic_cache();
92 int entry = dictionary->FindEntry(isolate, flags);
93 DCHECK(entry != -1);
94 Object* code = dictionary->ValueAt(entry);
95 // This might be called during the marking phase of the collector
96 // hence the unchecked cast.
97 return reinterpret_cast<Code*>(code);
98}
99
100
101static void FillCache(Isolate* isolate, Handle<Code> code) {
102 Handle<UnseededNumberDictionary> dictionary = UnseededNumberDictionary::Set(
103 isolate->factory()->non_monomorphic_cache(), code->flags(), code);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000104 isolate->heap()->SetRootNonMonomorphicCache(*dictionary);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000105}
106
107
108Handle<Code> PropertyICCompiler::ComputeStore(Isolate* isolate,
109 InlineCacheState ic_state,
110 ExtraICState extra_state) {
111 Code::Flags flags = Code::ComputeFlags(Code::STORE_IC, ic_state, extra_state);
112 Handle<UnseededNumberDictionary> cache =
113 isolate->factory()->non_monomorphic_cache();
114 int entry = cache->FindEntry(isolate, flags);
115 if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry)));
116
117 PropertyICCompiler compiler(isolate, Code::STORE_IC);
118 Handle<Code> code;
119 if (ic_state == UNINITIALIZED) {
120 code = compiler.CompileStoreInitialize(flags);
121 } else if (ic_state == PREMONOMORPHIC) {
122 code = compiler.CompileStorePreMonomorphic(flags);
123 } else if (ic_state == GENERIC) {
124 code = compiler.CompileStoreGeneric(flags);
125 } else if (ic_state == MEGAMORPHIC) {
126 code = compiler.CompileStoreMegamorphic(flags);
127 } else {
128 UNREACHABLE();
129 }
130
131 FillCache(isolate, code);
132 return code;
133}
134
135
136Handle<Code> PropertyICCompiler::ComputeCompareNil(Handle<Map> receiver_map,
137 CompareNilICStub* stub) {
138 Isolate* isolate = receiver_map->GetIsolate();
139 Handle<String> name(isolate->heap()->empty_string());
140 if (!receiver_map->is_dictionary_map()) {
141 Handle<Code> cached_ic =
142 Find(name, receiver_map, Code::COMPARE_NIL_IC, stub->GetExtraICState());
143 if (!cached_ic.is_null()) return cached_ic;
144 }
145
146 Code::FindAndReplacePattern pattern;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400147 Handle<WeakCell> cell = Map::WeakCellForMap(receiver_map);
148 pattern.Add(isolate->factory()->meta_map(), cell);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000149 Handle<Code> ic = stub->GetCodeCopy(pattern);
150
151 if (!receiver_map->is_dictionary_map()) {
152 Map::UpdateCodeCache(receiver_map, name, ic);
153 }
154
155 return ic;
156}
157
158
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000159void PropertyICCompiler::ComputeKeyedStorePolymorphicHandlers(
160 MapHandleList* receiver_maps, MapHandleList* transitioned_maps,
161 CodeHandleList* handlers, KeyedAccessStoreMode store_mode,
162 LanguageMode language_mode) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000163 Isolate* isolate = receiver_maps->at(0)->GetIsolate();
164 DCHECK(store_mode == STANDARD_STORE ||
165 store_mode == STORE_AND_GROW_NO_TRANSITION ||
166 store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS ||
167 store_mode == STORE_NO_TRANSITION_HANDLE_COW);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000168 ExtraICState extra_state =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000169 KeyedStoreIC::ComputeExtraICState(language_mode, store_mode);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000170 PropertyICCompiler compiler(isolate, Code::KEYED_STORE_IC, extra_state);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000171 compiler.CompileKeyedStorePolymorphicHandlers(
172 receiver_maps, transitioned_maps, handlers, store_mode);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000173}
174
175
176Handle<Code> PropertyICCompiler::CompileLoadInitialize(Code::Flags flags) {
177 LoadIC::GenerateInitialize(masm());
178 Handle<Code> code = GetCodeWithFlags(flags, "CompileLoadInitialize");
179 PROFILE(isolate(), CodeCreateEvent(Logger::LOAD_INITIALIZE_TAG, *code, 0));
180 return code;
181}
182
183
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000184Handle<Code> PropertyICCompiler::CompileStoreInitialize(Code::Flags flags) {
185 StoreIC::GenerateInitialize(masm());
186 Handle<Code> code = GetCodeWithFlags(flags, "CompileStoreInitialize");
187 PROFILE(isolate(), CodeCreateEvent(Logger::STORE_INITIALIZE_TAG, *code, 0));
188 return code;
189}
190
191
192Handle<Code> PropertyICCompiler::CompileStorePreMonomorphic(Code::Flags flags) {
193 StoreIC::GeneratePreMonomorphic(masm());
194 Handle<Code> code = GetCodeWithFlags(flags, "CompileStorePreMonomorphic");
195 PROFILE(isolate(),
196 CodeCreateEvent(Logger::STORE_PREMONOMORPHIC_TAG, *code, 0));
197 return code;
198}
199
200
201Handle<Code> PropertyICCompiler::CompileStoreGeneric(Code::Flags flags) {
202 ExtraICState extra_state = Code::ExtractExtraICStateFromFlags(flags);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000203 LanguageMode language_mode = StoreICState::GetLanguageMode(extra_state);
204 GenerateRuntimeSetProperty(masm(), language_mode);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000205 Handle<Code> code = GetCodeWithFlags(flags, "CompileStoreGeneric");
206 PROFILE(isolate(), CodeCreateEvent(Logger::STORE_GENERIC_TAG, *code, 0));
207 return code;
208}
209
210
211Handle<Code> PropertyICCompiler::CompileStoreMegamorphic(Code::Flags flags) {
212 StoreIC::GenerateMegamorphic(masm());
213 Handle<Code> code = GetCodeWithFlags(flags, "CompileStoreMegamorphic");
214 PROFILE(isolate(), CodeCreateEvent(Logger::STORE_MEGAMORPHIC_TAG, *code, 0));
215 return code;
216}
217
218
219Handle<Code> PropertyICCompiler::GetCode(Code::Kind kind, Code::StubType type,
220 Handle<Name> name,
221 InlineCacheState state) {
222 Code::Flags flags =
223 Code::ComputeFlags(kind, state, extra_ic_state_, type, cache_holder());
224 Handle<Code> code = GetCodeWithFlags(flags, name);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000225 PROFILE(isolate(), CodeCreateEvent(log_kind(code), *code, *name));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000226#ifdef DEBUG
227 code->VerifyEmbeddedObjects();
228#endif
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000229 return code;
230}
231
232
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000233void PropertyICCompiler::CompileKeyedStorePolymorphicHandlers(
234 MapHandleList* receiver_maps, MapHandleList* transitioned_maps,
235 CodeHandleList* handlers, KeyedAccessStoreMode store_mode) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000236 for (int i = 0; i < receiver_maps->length(); ++i) {
237 Handle<Map> receiver_map(receiver_maps->at(i));
238 Handle<Code> cached_stub;
239 Handle<Map> transitioned_map =
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000240 Map::FindTransitionedMap(receiver_map, receiver_maps);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000241
242 // TODO(mvstanton): The code below is doing pessimistic elements
243 // transitions. I would like to stop doing that and rely on Allocation Site
244 // Tracking to do a better job of ensuring the data types are what they need
245 // to be. Not all the elements are in place yet, pessimistic elements
246 // transitions are still important for performance.
247 bool is_js_array = receiver_map->instance_type() == JS_ARRAY_TYPE;
248 ElementsKind elements_kind = receiver_map->elements_kind();
249 if (!transitioned_map.is_null()) {
250 cached_stub =
251 ElementsTransitionAndStoreStub(isolate(), elements_kind,
252 transitioned_map->elements_kind(),
253 is_js_array, store_mode).GetCode();
254 } else if (receiver_map->instance_type() < FIRST_JS_RECEIVER_TYPE) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000255 // TODO(mvstanton): Consider embedding store_mode in the state of the slow
256 // keyed store ic for uniformity.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000257 cached_stub = isolate()->builtins()->KeyedStoreIC_Slow();
258 } else {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000259 if (IsSloppyArgumentsElements(elements_kind)) {
260 cached_stub =
261 KeyedStoreSloppyArgumentsStub(isolate(), store_mode).GetCode();
262 } else if (receiver_map->has_fast_elements() ||
263 receiver_map->has_fixed_typed_array_elements()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000264 cached_stub = StoreFastElementStub(isolate(), is_js_array,
265 elements_kind, store_mode).GetCode();
266 } else {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000267 cached_stub =
268 StoreElementStub(isolate(), elements_kind, store_mode).GetCode();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000269 }
270 }
271 DCHECK(!cached_stub.is_null());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000272 handlers->Add(cached_stub);
273 transitioned_maps->Add(transitioned_map);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000274 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000275}
276
277
278#define __ ACCESS_MASM(masm())
279
280
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000281Handle<Code> PropertyICCompiler::CompileKeyedStoreMonomorphicHandler(
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000282 Handle<Map> receiver_map, KeyedAccessStoreMode store_mode) {
283 ElementsKind elements_kind = receiver_map->elements_kind();
284 bool is_jsarray = receiver_map->instance_type() == JS_ARRAY_TYPE;
285 Handle<Code> stub;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000286 if (receiver_map->has_sloppy_arguments_elements()) {
287 stub = KeyedStoreSloppyArgumentsStub(isolate(), store_mode).GetCode();
288 } else if (receiver_map->has_fast_elements() ||
289 receiver_map->has_fixed_typed_array_elements()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000290 stub = StoreFastElementStub(isolate(), is_jsarray, elements_kind,
291 store_mode).GetCode();
292 } else {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000293 stub = StoreElementStub(isolate(), elements_kind, store_mode).GetCode();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000294 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000295 return stub;
296}
297
298
299Handle<Code> PropertyICCompiler::CompileKeyedStoreMonomorphic(
300 Handle<Map> receiver_map, KeyedAccessStoreMode store_mode) {
301 Handle<Code> stub =
302 CompileKeyedStoreMonomorphicHandler(receiver_map, store_mode);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000303
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400304 Handle<WeakCell> cell = Map::WeakCellForMap(receiver_map);
305
306 __ DispatchWeakMap(receiver(), scratch1(), scratch2(), cell, stub,
307 DO_SMI_CHECK);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000308
309 TailCallBuiltin(masm(), Builtins::kKeyedStoreIC_Miss);
310
311 return GetCode(kind(), Code::NORMAL, factory()->empty_string());
312}
313
314
315#undef __
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000316} // namespace internal
317} // namespace v8