OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/v8.h" | 5 #include "src/v8.h" |
6 | 6 |
7 #include "src/api.h" | 7 #include "src/api.h" |
8 #include "src/arguments.h" | 8 #include "src/arguments.h" |
9 #include "src/ast.h" | 9 #include "src/ast.h" |
10 #include "src/code-stubs.h" | 10 #include "src/code-stubs.h" |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
50 | 50 |
51 // Make sure that the code type and cache holder are not included in the hash. | 51 // Make sure that the code type and cache holder are not included in the hash. |
52 ASSERT(Code::ExtractTypeFromFlags(flags) == 0); | 52 ASSERT(Code::ExtractTypeFromFlags(flags) == 0); |
53 ASSERT(Code::ExtractCacheHolderFromFlags(flags) == 0); | 53 ASSERT(Code::ExtractCacheHolderFromFlags(flags) == 0); |
54 | 54 |
55 return flags; | 55 return flags; |
56 } | 56 } |
57 | 57 |
58 | 58 |
59 Code* StubCache::Set(Name* name, Map* map, Code* code) { | 59 Code* StubCache::Set(Name* name, Map* map, Code* code) { |
60 Code::Flags flags = CommonStubCacheChecks(name, map, code->flags(), heap()); | 60 Code::Flags flags = |
| 61 CommonStubCacheChecks(name, map, code->flags(), isolate()->heap()); |
61 | 62 |
62 // Compute the primary entry. | 63 // Compute the primary entry. |
63 int primary_offset = PrimaryOffset(name, flags, map); | 64 int primary_offset = PrimaryOffset(name, flags, map); |
64 Entry* primary = entry(primary_, primary_offset); | 65 Entry* primary = entry(primary_, primary_offset); |
65 Code* old_code = primary->value; | 66 Code* old_code = primary->value; |
66 | 67 |
67 // If the primary entry has useful data in it, we retire it to the | 68 // If the primary entry has useful data in it, we retire it to the |
68 // secondary cache before overwriting it. | 69 // secondary cache before overwriting it. |
69 if (old_code != isolate_->builtins()->builtin(Builtins::kIllegal)) { | 70 if (old_code != isolate_->builtins()->builtin(Builtins::kIllegal)) { |
70 Map* old_map = primary->map; | 71 Map* old_map = primary->map; |
71 Code::Flags old_flags = | 72 Code::Flags old_flags = |
72 Code::RemoveTypeAndHolderFromFlags(old_code->flags()); | 73 Code::RemoveTypeAndHolderFromFlags(old_code->flags()); |
73 int seed = PrimaryOffset(primary->key, old_flags, old_map); | 74 int seed = PrimaryOffset(primary->key, old_flags, old_map); |
74 int secondary_offset = SecondaryOffset(primary->key, old_flags, seed); | 75 int secondary_offset = SecondaryOffset(primary->key, old_flags, seed); |
75 Entry* secondary = entry(secondary_, secondary_offset); | 76 Entry* secondary = entry(secondary_, secondary_offset); |
76 *secondary = *primary; | 77 *secondary = *primary; |
77 } | 78 } |
78 | 79 |
79 // Update primary cache. | 80 // Update primary cache. |
80 primary->key = name; | 81 primary->key = name; |
81 primary->value = code; | 82 primary->value = code; |
82 primary->map = map; | 83 primary->map = map; |
83 isolate()->counters()->megamorphic_stub_cache_updates()->Increment(); | 84 isolate()->counters()->megamorphic_stub_cache_updates()->Increment(); |
84 return code; | 85 return code; |
85 } | 86 } |
86 | 87 |
87 | 88 |
88 Code* StubCache::Get(Name* name, Map* map, Code::Flags flags) { | 89 Code* StubCache::Get(Name* name, Map* map, Code::Flags flags) { |
89 flags = CommonStubCacheChecks(name, map, flags, heap()); | 90 flags = CommonStubCacheChecks(name, map, flags, isolate()->heap()); |
90 int primary_offset = PrimaryOffset(name, flags, map); | 91 int primary_offset = PrimaryOffset(name, flags, map); |
91 Entry* primary = entry(primary_, primary_offset); | 92 Entry* primary = entry(primary_, primary_offset); |
92 if (primary->key == name && primary->map == map) { | 93 if (primary->key == name && primary->map == map) { |
93 return primary->value; | 94 return primary->value; |
94 } | 95 } |
95 int secondary_offset = SecondaryOffset(name, flags, primary_offset); | 96 int secondary_offset = SecondaryOffset(name, flags, primary_offset); |
96 Entry* secondary = entry(secondary_, secondary_offset); | 97 Entry* secondary = entry(secondary_, secondary_offset); |
97 if (secondary->key == name && secondary->map == map) { | 98 if (secondary->key == name && secondary->map == map) { |
98 return secondary->value; | 99 return secondary->value; |
99 } | 100 } |
(...skipping 21 matching lines...) Expand all Loading... |
121 Code::StubType type) { | 122 Code::StubType type) { |
122 Code::Flags flags = Code::ComputeHandlerFlags(kind, type, cache_holder); | 123 Code::Flags flags = Code::ComputeHandlerFlags(kind, type, cache_holder); |
123 | 124 |
124 Handle<Object> probe(stub_holder->FindInCodeCache(*name, flags), | 125 Handle<Object> probe(stub_holder->FindInCodeCache(*name, flags), |
125 name->GetIsolate()); | 126 name->GetIsolate()); |
126 if (probe->IsCode()) return Handle<Code>::cast(probe); | 127 if (probe->IsCode()) return Handle<Code>::cast(probe); |
127 return Handle<Code>::null(); | 128 return Handle<Code>::null(); |
128 } | 129 } |
129 | 130 |
130 | 131 |
131 Handle<Code> StubCache::ComputeMonomorphicIC( | 132 Handle<Code> PropertyICCompiler::ComputeMonomorphicIC( |
132 Code::Kind kind, | 133 Code::Kind kind, Handle<Name> name, Handle<HeapType> type, |
133 Handle<Name> name, | 134 Handle<Code> handler, ExtraICState extra_ic_state) { |
134 Handle<HeapType> type, | |
135 Handle<Code> handler, | |
136 ExtraICState extra_ic_state) { | |
137 CacheHolderFlag flag; | 135 CacheHolderFlag flag; |
138 Handle<Map> stub_holder = IC::GetICCacheHolder(*type, isolate(), &flag); | 136 Isolate* isolate = name->GetIsolate(); |
| 137 Handle<Map> stub_holder = IC::GetICCacheHolder(*type, isolate, &flag); |
139 | 138 |
140 Handle<Code> ic; | 139 Handle<Code> ic; |
141 // There are multiple string maps that all use the same prototype. That | 140 // There are multiple string maps that all use the same prototype. That |
142 // prototype cannot hold multiple handlers, one for each of the string maps, | 141 // prototype cannot hold multiple handlers, one for each of the string maps, |
143 // for a single name. Hence, turn off caching of the IC. | 142 // for a single name. Hence, turn off caching of the IC. |
144 bool can_be_cached = !type->Is(HeapType::String()); | 143 bool can_be_cached = !type->Is(HeapType::String()); |
145 if (can_be_cached) { | 144 if (can_be_cached) { |
146 ic = | 145 ic = Find(name, stub_holder, kind, extra_ic_state, flag); |
147 PropertyICCompiler::Find(name, stub_holder, kind, extra_ic_state, flag); | |
148 if (!ic.is_null()) return ic; | 146 if (!ic.is_null()) return ic; |
149 } | 147 } |
150 | 148 |
151 #ifdef DEBUG | 149 #ifdef DEBUG |
152 if (kind == Code::KEYED_STORE_IC) { | 150 if (kind == Code::KEYED_STORE_IC) { |
153 ASSERT(STANDARD_STORE == | 151 ASSERT(STANDARD_STORE == |
154 KeyedStoreIC::GetKeyedAccessStoreMode(extra_ic_state)); | 152 KeyedStoreIC::GetKeyedAccessStoreMode(extra_ic_state)); |
155 } | 153 } |
156 #endif | 154 #endif |
157 | 155 |
158 PropertyICCompiler ic_compiler(isolate(), kind, extra_ic_state, flag); | 156 PropertyICCompiler ic_compiler(isolate, kind, extra_ic_state, flag); |
159 ic = ic_compiler.CompileMonomorphic(type, handler, name, PROPERTY); | 157 ic = ic_compiler.CompileMonomorphic(type, handler, name, PROPERTY); |
160 | 158 |
161 if (can_be_cached) Map::UpdateCodeCache(stub_holder, name, ic); | 159 if (can_be_cached) Map::UpdateCodeCache(stub_holder, name, ic); |
162 return ic; | 160 return ic; |
163 } | 161 } |
164 | 162 |
165 | 163 |
166 Handle<Code> StubCache::ComputeLoadNonexistent(Handle<Name> name, | 164 Handle<Code> NamedLoadHandlerCompiler::ComputeLoadNonexistent( |
167 Handle<HeapType> type) { | 165 Handle<Name> name, Handle<HeapType> type) { |
168 Handle<Map> receiver_map = IC::TypeToMap(*type, isolate()); | 166 Isolate* isolate = name->GetIsolate(); |
| 167 Handle<Map> receiver_map = IC::TypeToMap(*type, isolate); |
169 if (receiver_map->prototype()->IsNull()) { | 168 if (receiver_map->prototype()->IsNull()) { |
170 // TODO(jkummerow/verwaest): If there is no prototype and the property | 169 // TODO(jkummerow/verwaest): If there is no prototype and the property |
171 // is nonexistent, introduce a builtin to handle this (fast properties | 170 // is nonexistent, introduce a builtin to handle this (fast properties |
172 // -> return undefined, dictionary properties -> do negative lookup). | 171 // -> return undefined, dictionary properties -> do negative lookup). |
173 return Handle<Code>(); | 172 return Handle<Code>(); |
174 } | 173 } |
175 CacheHolderFlag flag; | 174 CacheHolderFlag flag; |
176 Handle<Map> stub_holder_map = | 175 Handle<Map> stub_holder_map = |
177 IC::GetHandlerCacheHolder(*type, false, isolate(), &flag); | 176 IC::GetHandlerCacheHolder(*type, false, isolate, &flag); |
178 | 177 |
179 // If no dictionary mode objects are present in the prototype chain, the load | 178 // If no dictionary mode objects are present in the prototype chain, the load |
180 // nonexistent IC stub can be shared for all names for a given map and we use | 179 // nonexistent IC stub can be shared for all names for a given map and we use |
181 // the empty string for the map cache in that case. If there are dictionary | 180 // the empty string for the map cache in that case. If there are dictionary |
182 // mode objects involved, we need to do negative lookups in the stub and | 181 // mode objects involved, we need to do negative lookups in the stub and |
183 // therefore the stub will be specific to the name. | 182 // therefore the stub will be specific to the name. |
184 Handle<Name> cache_name = | 183 Handle<Name> cache_name = |
185 receiver_map->is_dictionary_map() | 184 receiver_map->is_dictionary_map() |
186 ? name | 185 ? name |
187 : Handle<Name>::cast(isolate()->factory()->nonexistent_symbol()); | 186 : Handle<Name>::cast(isolate->factory()->nonexistent_symbol()); |
188 Handle<Map> current_map = stub_holder_map; | 187 Handle<Map> current_map = stub_holder_map; |
189 Handle<JSObject> last(JSObject::cast(receiver_map->prototype())); | 188 Handle<JSObject> last(JSObject::cast(receiver_map->prototype())); |
190 while (true) { | 189 while (true) { |
191 if (current_map->is_dictionary_map()) cache_name = name; | 190 if (current_map->is_dictionary_map()) cache_name = name; |
192 if (current_map->prototype()->IsNull()) break; | 191 if (current_map->prototype()->IsNull()) break; |
193 last = handle(JSObject::cast(current_map->prototype())); | 192 last = handle(JSObject::cast(current_map->prototype())); |
194 current_map = handle(last->map()); | 193 current_map = handle(last->map()); |
195 } | 194 } |
196 // Compile the stub that is either shared for all names or | 195 // Compile the stub that is either shared for all names or |
197 // name specific if there are global objects involved. | 196 // name specific if there are global objects involved. |
198 Handle<Code> handler = PropertyHandlerCompiler::Find( | 197 Handle<Code> handler = PropertyHandlerCompiler::Find( |
199 cache_name, stub_holder_map, Code::LOAD_IC, flag, Code::FAST); | 198 cache_name, stub_holder_map, Code::LOAD_IC, flag, Code::FAST); |
200 if (!handler.is_null()) return handler; | 199 if (!handler.is_null()) return handler; |
201 | 200 |
202 NamedLoadHandlerCompiler compiler(isolate_, flag); | 201 NamedLoadHandlerCompiler compiler(isolate, flag); |
203 handler = compiler.CompileLoadNonexistent(type, last, cache_name); | 202 handler = compiler.CompileLoadNonexistent(type, last, cache_name); |
204 Map::UpdateCodeCache(stub_holder_map, cache_name, handler); | 203 Map::UpdateCodeCache(stub_holder_map, cache_name, handler); |
205 return handler; | 204 return handler; |
206 } | 205 } |
207 | 206 |
208 | 207 |
209 Handle<Code> StubCache::ComputeKeyedLoadElement(Handle<Map> receiver_map) { | 208 Handle<Code> PropertyICCompiler::ComputeKeyedLoadElement( |
| 209 Handle<Map> receiver_map) { |
| 210 Isolate* isolate = receiver_map->GetIsolate(); |
210 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC); | 211 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC); |
211 Handle<Name> name = | 212 Handle<Name> name = isolate->factory()->KeyedLoadElementMonomorphic_string(); |
212 isolate()->factory()->KeyedLoadElementMonomorphic_string(); | |
213 | 213 |
214 Handle<Object> probe(receiver_map->FindInCodeCache(*name, flags), isolate_); | 214 Handle<Object> probe(receiver_map->FindInCodeCache(*name, flags), isolate); |
215 if (probe->IsCode()) return Handle<Code>::cast(probe); | 215 if (probe->IsCode()) return Handle<Code>::cast(probe); |
216 | 216 |
217 ElementsKind elements_kind = receiver_map->elements_kind(); | 217 ElementsKind elements_kind = receiver_map->elements_kind(); |
218 Handle<Code> stub; | 218 Handle<Code> stub; |
219 if (receiver_map->has_fast_elements() || | 219 if (receiver_map->has_fast_elements() || |
220 receiver_map->has_external_array_elements() || | 220 receiver_map->has_external_array_elements() || |
221 receiver_map->has_fixed_typed_array_elements()) { | 221 receiver_map->has_fixed_typed_array_elements()) { |
222 stub = KeyedLoadFastElementStub( | 222 stub = KeyedLoadFastElementStub( |
223 isolate(), receiver_map->instance_type() == JS_ARRAY_TYPE, | 223 isolate, receiver_map->instance_type() == JS_ARRAY_TYPE, |
224 elements_kind).GetCode(); | 224 elements_kind).GetCode(); |
225 } else { | 225 } else { |
226 stub = FLAG_compiled_keyed_dictionary_loads | 226 stub = FLAG_compiled_keyed_dictionary_loads |
227 ? KeyedLoadDictionaryElementStub(isolate()).GetCode() | 227 ? KeyedLoadDictionaryElementStub(isolate).GetCode() |
228 : KeyedLoadDictionaryElementPlatformStub(isolate()).GetCode(); | 228 : KeyedLoadDictionaryElementPlatformStub(isolate).GetCode(); |
229 } | 229 } |
230 PropertyICCompiler compiler(isolate(), Code::KEYED_LOAD_IC); | 230 PropertyICCompiler compiler(isolate, Code::KEYED_LOAD_IC); |
231 Handle<Code> code = | 231 Handle<Code> code = |
232 compiler.CompileMonomorphic(HeapType::Class(receiver_map, isolate()), | 232 compiler.CompileMonomorphic(HeapType::Class(receiver_map, isolate), stub, |
233 stub, factory()->empty_string(), ELEMENT); | 233 isolate->factory()->empty_string(), ELEMENT); |
234 | 234 |
235 Map::UpdateCodeCache(receiver_map, name, code); | 235 Map::UpdateCodeCache(receiver_map, name, code); |
236 return code; | 236 return code; |
237 } | 237 } |
238 | 238 |
239 | 239 |
240 Handle<Code> StubCache::ComputeKeyedStoreElement( | 240 Handle<Code> PropertyICCompiler::ComputeKeyedStoreElement( |
241 Handle<Map> receiver_map, | 241 Handle<Map> receiver_map, StrictMode strict_mode, |
242 StrictMode strict_mode, | |
243 KeyedAccessStoreMode store_mode) { | 242 KeyedAccessStoreMode store_mode) { |
| 243 Isolate* isolate = receiver_map->GetIsolate(); |
244 ExtraICState extra_state = | 244 ExtraICState extra_state = |
245 KeyedStoreIC::ComputeExtraICState(strict_mode, store_mode); | 245 KeyedStoreIC::ComputeExtraICState(strict_mode, store_mode); |
246 Code::Flags flags = | 246 Code::Flags flags = |
247 Code::ComputeMonomorphicFlags(Code::KEYED_STORE_IC, extra_state); | 247 Code::ComputeMonomorphicFlags(Code::KEYED_STORE_IC, extra_state); |
248 | 248 |
249 ASSERT(store_mode == STANDARD_STORE || | 249 ASSERT(store_mode == STANDARD_STORE || |
250 store_mode == STORE_AND_GROW_NO_TRANSITION || | 250 store_mode == STORE_AND_GROW_NO_TRANSITION || |
251 store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS || | 251 store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS || |
252 store_mode == STORE_NO_TRANSITION_HANDLE_COW); | 252 store_mode == STORE_NO_TRANSITION_HANDLE_COW); |
253 | 253 |
254 Handle<String> name = | 254 Handle<String> name = |
255 isolate()->factory()->KeyedStoreElementMonomorphic_string(); | 255 isolate->factory()->KeyedStoreElementMonomorphic_string(); |
256 Handle<Object> probe(receiver_map->FindInCodeCache(*name, flags), isolate_); | 256 Handle<Object> probe(receiver_map->FindInCodeCache(*name, flags), isolate); |
257 if (probe->IsCode()) return Handle<Code>::cast(probe); | 257 if (probe->IsCode()) return Handle<Code>::cast(probe); |
258 | 258 |
259 PropertyICCompiler compiler(isolate(), Code::KEYED_STORE_IC, extra_state); | 259 PropertyICCompiler compiler(isolate, Code::KEYED_STORE_IC, extra_state); |
260 Handle<Code> code = | 260 Handle<Code> code = |
261 compiler.CompileIndexedStoreMonomorphic(receiver_map, store_mode); | 261 compiler.CompileIndexedStoreMonomorphic(receiver_map, store_mode); |
262 | 262 |
263 Map::UpdateCodeCache(receiver_map, name, code); | 263 Map::UpdateCodeCache(receiver_map, name, code); |
264 ASSERT(KeyedStoreIC::GetKeyedAccessStoreMode(code->extra_ic_state()) | 264 ASSERT(KeyedStoreIC::GetKeyedAccessStoreMode(code->extra_ic_state()) |
265 == store_mode); | 265 == store_mode); |
266 return code; | 266 return code; |
267 } | 267 } |
268 | 268 |
269 | 269 |
270 #define CALL_LOGGER_TAG(kind, type) (Logger::KEYED_##type) | 270 #define CALL_LOGGER_TAG(kind, type) (Logger::KEYED_##type) |
271 | 271 |
272 static void FillCache(Isolate* isolate, Handle<Code> code) { | 272 static void FillCache(Isolate* isolate, Handle<Code> code) { |
273 Handle<UnseededNumberDictionary> dictionary = | 273 Handle<UnseededNumberDictionary> dictionary = |
274 UnseededNumberDictionary::Set(isolate->factory()->non_monomorphic_cache(), | 274 UnseededNumberDictionary::Set(isolate->factory()->non_monomorphic_cache(), |
275 code->flags(), | 275 code->flags(), |
276 code); | 276 code); |
277 isolate->heap()->public_set_non_monomorphic_cache(*dictionary); | 277 isolate->heap()->public_set_non_monomorphic_cache(*dictionary); |
278 } | 278 } |
279 | 279 |
280 | 280 |
281 Code* StubCache::FindPreMonomorphicIC(Code::Kind kind, ExtraICState state) { | 281 Code* PropertyICCompiler::FindPreMonomorphicIC(Isolate* isolate, |
| 282 Code::Kind kind, |
| 283 ExtraICState state) { |
282 Code::Flags flags = Code::ComputeFlags(kind, PREMONOMORPHIC, state); | 284 Code::Flags flags = Code::ComputeFlags(kind, PREMONOMORPHIC, state); |
283 UnseededNumberDictionary* dictionary = | 285 UnseededNumberDictionary* dictionary = |
284 isolate()->heap()->non_monomorphic_cache(); | 286 isolate->heap()->non_monomorphic_cache(); |
285 int entry = dictionary->FindEntry(isolate(), flags); | 287 int entry = dictionary->FindEntry(isolate, flags); |
286 ASSERT(entry != -1); | 288 ASSERT(entry != -1); |
287 Object* code = dictionary->ValueAt(entry); | 289 Object* code = dictionary->ValueAt(entry); |
288 // This might be called during the marking phase of the collector | 290 // This might be called during the marking phase of the collector |
289 // hence the unchecked cast. | 291 // hence the unchecked cast. |
290 return reinterpret_cast<Code*>(code); | 292 return reinterpret_cast<Code*>(code); |
291 } | 293 } |
292 | 294 |
293 | 295 |
294 Handle<Code> StubCache::ComputeLoad(InlineCacheState ic_state, | 296 Handle<Code> PropertyICCompiler::ComputeLoad(Isolate* isolate, |
295 ExtraICState extra_state) { | 297 InlineCacheState ic_state, |
| 298 ExtraICState extra_state) { |
296 Code::Flags flags = Code::ComputeFlags(Code::LOAD_IC, ic_state, extra_state); | 299 Code::Flags flags = Code::ComputeFlags(Code::LOAD_IC, ic_state, extra_state); |
297 Handle<UnseededNumberDictionary> cache = | 300 Handle<UnseededNumberDictionary> cache = |
298 isolate_->factory()->non_monomorphic_cache(); | 301 isolate->factory()->non_monomorphic_cache(); |
299 int entry = cache->FindEntry(isolate_, flags); | 302 int entry = cache->FindEntry(isolate, flags); |
300 if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry))); | 303 if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry))); |
301 | 304 |
302 PropertyICCompiler compiler(isolate_, Code::LOAD_IC); | 305 PropertyICCompiler compiler(isolate, Code::LOAD_IC); |
303 Handle<Code> code; | 306 Handle<Code> code; |
304 if (ic_state == UNINITIALIZED) { | 307 if (ic_state == UNINITIALIZED) { |
305 code = compiler.CompileLoadInitialize(flags); | 308 code = compiler.CompileLoadInitialize(flags); |
306 } else if (ic_state == PREMONOMORPHIC) { | 309 } else if (ic_state == PREMONOMORPHIC) { |
307 code = compiler.CompileLoadPreMonomorphic(flags); | 310 code = compiler.CompileLoadPreMonomorphic(flags); |
308 } else if (ic_state == MEGAMORPHIC) { | 311 } else if (ic_state == MEGAMORPHIC) { |
309 code = compiler.CompileLoadMegamorphic(flags); | 312 code = compiler.CompileLoadMegamorphic(flags); |
310 } else { | 313 } else { |
311 UNREACHABLE(); | 314 UNREACHABLE(); |
312 } | 315 } |
313 FillCache(isolate_, code); | 316 FillCache(isolate, code); |
314 return code; | 317 return code; |
315 } | 318 } |
316 | 319 |
317 | 320 |
318 Handle<Code> StubCache::ComputeStore(InlineCacheState ic_state, | 321 Handle<Code> PropertyICCompiler::ComputeStore(Isolate* isolate, |
319 ExtraICState extra_state) { | 322 InlineCacheState ic_state, |
| 323 ExtraICState extra_state) { |
320 Code::Flags flags = Code::ComputeFlags(Code::STORE_IC, ic_state, extra_state); | 324 Code::Flags flags = Code::ComputeFlags(Code::STORE_IC, ic_state, extra_state); |
321 Handle<UnseededNumberDictionary> cache = | 325 Handle<UnseededNumberDictionary> cache = |
322 isolate_->factory()->non_monomorphic_cache(); | 326 isolate->factory()->non_monomorphic_cache(); |
323 int entry = cache->FindEntry(isolate_, flags); | 327 int entry = cache->FindEntry(isolate, flags); |
324 if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry))); | 328 if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry))); |
325 | 329 |
326 PropertyICCompiler compiler(isolate_, Code::STORE_IC); | 330 PropertyICCompiler compiler(isolate, Code::STORE_IC); |
327 Handle<Code> code; | 331 Handle<Code> code; |
328 if (ic_state == UNINITIALIZED) { | 332 if (ic_state == UNINITIALIZED) { |
329 code = compiler.CompileStoreInitialize(flags); | 333 code = compiler.CompileStoreInitialize(flags); |
330 } else if (ic_state == PREMONOMORPHIC) { | 334 } else if (ic_state == PREMONOMORPHIC) { |
331 code = compiler.CompileStorePreMonomorphic(flags); | 335 code = compiler.CompileStorePreMonomorphic(flags); |
332 } else if (ic_state == GENERIC) { | 336 } else if (ic_state == GENERIC) { |
333 code = compiler.CompileStoreGeneric(flags); | 337 code = compiler.CompileStoreGeneric(flags); |
334 } else if (ic_state == MEGAMORPHIC) { | 338 } else if (ic_state == MEGAMORPHIC) { |
335 code = compiler.CompileStoreMegamorphic(flags); | 339 code = compiler.CompileStoreMegamorphic(flags); |
336 } else { | 340 } else { |
337 UNREACHABLE(); | 341 UNREACHABLE(); |
338 } | 342 } |
339 | 343 |
340 FillCache(isolate_, code); | 344 FillCache(isolate, code); |
341 return code; | 345 return code; |
342 } | 346 } |
343 | 347 |
344 | 348 |
345 Handle<Code> StubCache::ComputeCompareNil(Handle<Map> receiver_map, | 349 Handle<Code> PropertyICCompiler::ComputeCompareNil(Handle<Map> receiver_map, |
346 CompareNilICStub* stub) { | 350 CompareNilICStub* stub) { |
347 Handle<String> name(isolate_->heap()->empty_string()); | 351 Isolate* isolate = receiver_map->GetIsolate(); |
| 352 Handle<String> name(isolate->heap()->empty_string()); |
348 if (!receiver_map->is_shared()) { | 353 if (!receiver_map->is_shared()) { |
349 Handle<Code> cached_ic = PropertyICCompiler::Find( | 354 Handle<Code> cached_ic = |
350 name, receiver_map, Code::COMPARE_NIL_IC, stub->GetExtraICState()); | 355 Find(name, receiver_map, Code::COMPARE_NIL_IC, stub->GetExtraICState()); |
351 if (!cached_ic.is_null()) return cached_ic; | 356 if (!cached_ic.is_null()) return cached_ic; |
352 } | 357 } |
353 | 358 |
354 Code::FindAndReplacePattern pattern; | 359 Code::FindAndReplacePattern pattern; |
355 pattern.Add(isolate_->factory()->meta_map(), receiver_map); | 360 pattern.Add(isolate->factory()->meta_map(), receiver_map); |
356 Handle<Code> ic = stub->GetCodeCopy(pattern); | 361 Handle<Code> ic = stub->GetCodeCopy(pattern); |
357 | 362 |
358 if (!receiver_map->is_shared()) { | 363 if (!receiver_map->is_shared()) { |
359 Map::UpdateCodeCache(receiver_map, name, ic); | 364 Map::UpdateCodeCache(receiver_map, name, ic); |
360 } | 365 } |
361 | 366 |
362 return ic; | 367 return ic; |
363 } | 368 } |
364 | 369 |
365 | 370 |
366 // TODO(verwaest): Change this method so it takes in a TypeHandleList. | 371 // TODO(verwaest): Change this method so it takes in a TypeHandleList. |
367 Handle<Code> StubCache::ComputeLoadElementPolymorphic( | 372 Handle<Code> PropertyICCompiler::ComputeLoadElementPolymorphic( |
368 MapHandleList* receiver_maps) { | 373 MapHandleList* receiver_maps) { |
| 374 Isolate* isolate = receiver_maps->at(0)->GetIsolate(); |
369 Code::Flags flags = Code::ComputeFlags(Code::KEYED_LOAD_IC, POLYMORPHIC); | 375 Code::Flags flags = Code::ComputeFlags(Code::KEYED_LOAD_IC, POLYMORPHIC); |
370 Handle<PolymorphicCodeCache> cache = | 376 Handle<PolymorphicCodeCache> cache = |
371 isolate_->factory()->polymorphic_code_cache(); | 377 isolate->factory()->polymorphic_code_cache(); |
372 Handle<Object> probe = cache->Lookup(receiver_maps, flags); | 378 Handle<Object> probe = cache->Lookup(receiver_maps, flags); |
373 if (probe->IsCode()) return Handle<Code>::cast(probe); | 379 if (probe->IsCode()) return Handle<Code>::cast(probe); |
374 | 380 |
375 TypeHandleList types(receiver_maps->length()); | 381 TypeHandleList types(receiver_maps->length()); |
376 for (int i = 0; i < receiver_maps->length(); i++) { | 382 for (int i = 0; i < receiver_maps->length(); i++) { |
377 types.Add(HeapType::Class(receiver_maps->at(i), isolate())); | 383 types.Add(HeapType::Class(receiver_maps->at(i), isolate)); |
378 } | 384 } |
379 CodeHandleList handlers(receiver_maps->length()); | 385 CodeHandleList handlers(receiver_maps->length()); |
380 IndexedHandlerCompiler compiler(isolate_); | 386 IndexedHandlerCompiler compiler(isolate); |
381 compiler.CompileElementHandlers(receiver_maps, &handlers); | 387 compiler.CompileElementHandlers(receiver_maps, &handlers); |
382 PropertyICCompiler ic_compiler(isolate_, Code::KEYED_LOAD_IC); | 388 PropertyICCompiler ic_compiler(isolate, Code::KEYED_LOAD_IC); |
383 Handle<Code> code = ic_compiler.CompilePolymorphic( | 389 Handle<Code> code = ic_compiler.CompilePolymorphic( |
384 &types, &handlers, factory()->empty_string(), Code::NORMAL, ELEMENT); | 390 &types, &handlers, isolate->factory()->empty_string(), Code::NORMAL, |
| 391 ELEMENT); |
385 | 392 |
386 isolate()->counters()->keyed_load_polymorphic_stubs()->Increment(); | 393 isolate->counters()->keyed_load_polymorphic_stubs()->Increment(); |
387 | 394 |
388 PolymorphicCodeCache::Update(cache, receiver_maps, flags, code); | 395 PolymorphicCodeCache::Update(cache, receiver_maps, flags, code); |
389 return code; | 396 return code; |
390 } | 397 } |
391 | 398 |
392 | 399 |
393 Handle<Code> StubCache::ComputePolymorphicIC( | 400 Handle<Code> PropertyICCompiler::ComputePolymorphicIC( |
394 Code::Kind kind, | 401 Code::Kind kind, TypeHandleList* types, CodeHandleList* handlers, |
395 TypeHandleList* types, | 402 int valid_types, Handle<Name> name, ExtraICState extra_ic_state) { |
396 CodeHandleList* handlers, | |
397 int number_of_valid_types, | |
398 Handle<Name> name, | |
399 ExtraICState extra_ic_state) { | |
400 Handle<Code> handler = handlers->at(0); | 403 Handle<Code> handler = handlers->at(0); |
401 Code::StubType type = number_of_valid_types == 1 ? handler->type() | 404 Code::StubType type = valid_types == 1 ? handler->type() : Code::NORMAL; |
402 : Code::NORMAL; | |
403 ASSERT(kind == Code::LOAD_IC || kind == Code::STORE_IC); | 405 ASSERT(kind == Code::LOAD_IC || kind == Code::STORE_IC); |
404 PropertyICCompiler ic_compiler(isolate_, kind, extra_ic_state); | 406 PropertyICCompiler ic_compiler(name->GetIsolate(), kind, extra_ic_state); |
405 return ic_compiler.CompilePolymorphic(types, handlers, name, type, PROPERTY); | 407 return ic_compiler.CompilePolymorphic(types, handlers, name, type, PROPERTY); |
406 } | 408 } |
407 | 409 |
408 | 410 |
409 Handle<Code> StubCache::ComputeStoreElementPolymorphic( | 411 Handle<Code> PropertyICCompiler::ComputeStoreElementPolymorphic( |
410 MapHandleList* receiver_maps, | 412 MapHandleList* receiver_maps, KeyedAccessStoreMode store_mode, |
411 KeyedAccessStoreMode store_mode, | |
412 StrictMode strict_mode) { | 413 StrictMode strict_mode) { |
| 414 Isolate* isolate = receiver_maps->at(0)->GetIsolate(); |
413 ASSERT(store_mode == STANDARD_STORE || | 415 ASSERT(store_mode == STANDARD_STORE || |
414 store_mode == STORE_AND_GROW_NO_TRANSITION || | 416 store_mode == STORE_AND_GROW_NO_TRANSITION || |
415 store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS || | 417 store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS || |
416 store_mode == STORE_NO_TRANSITION_HANDLE_COW); | 418 store_mode == STORE_NO_TRANSITION_HANDLE_COW); |
417 Handle<PolymorphicCodeCache> cache = | 419 Handle<PolymorphicCodeCache> cache = |
418 isolate_->factory()->polymorphic_code_cache(); | 420 isolate->factory()->polymorphic_code_cache(); |
419 ExtraICState extra_state = KeyedStoreIC::ComputeExtraICState( | 421 ExtraICState extra_state = KeyedStoreIC::ComputeExtraICState( |
420 strict_mode, store_mode); | 422 strict_mode, store_mode); |
421 Code::Flags flags = | 423 Code::Flags flags = |
422 Code::ComputeFlags(Code::KEYED_STORE_IC, POLYMORPHIC, extra_state); | 424 Code::ComputeFlags(Code::KEYED_STORE_IC, POLYMORPHIC, extra_state); |
423 Handle<Object> probe = cache->Lookup(receiver_maps, flags); | 425 Handle<Object> probe = cache->Lookup(receiver_maps, flags); |
424 if (probe->IsCode()) return Handle<Code>::cast(probe); | 426 if (probe->IsCode()) return Handle<Code>::cast(probe); |
425 | 427 |
426 PropertyICCompiler compiler(isolate_, Code::KEYED_STORE_IC, extra_state); | 428 PropertyICCompiler compiler(isolate, Code::KEYED_STORE_IC, extra_state); |
427 Handle<Code> code = | 429 Handle<Code> code = |
428 compiler.CompileIndexedStorePolymorphic(receiver_maps, store_mode); | 430 compiler.CompileIndexedStorePolymorphic(receiver_maps, store_mode); |
429 PolymorphicCodeCache::Update(cache, receiver_maps, flags, code); | 431 PolymorphicCodeCache::Update(cache, receiver_maps, flags, code); |
430 return code; | 432 return code; |
431 } | 433 } |
432 | 434 |
433 | 435 |
434 void StubCache::Clear() { | 436 void StubCache::Clear() { |
435 Code* empty = isolate_->builtins()->builtin(Builtins::kIllegal); | 437 Code* empty = isolate_->builtins()->builtin(Builtins::kIllegal); |
436 for (int i = 0; i < kPrimaryTableSize; i++) { | 438 for (int i = 0; i < kPrimaryTableSize; i++) { |
437 primary_[i].key = heap()->empty_string(); | 439 primary_[i].key = isolate()->heap()->empty_string(); |
438 primary_[i].map = NULL; | 440 primary_[i].map = NULL; |
439 primary_[i].value = empty; | 441 primary_[i].value = empty; |
440 } | 442 } |
441 for (int j = 0; j < kSecondaryTableSize; j++) { | 443 for (int j = 0; j < kSecondaryTableSize; j++) { |
442 secondary_[j].key = heap()->empty_string(); | 444 secondary_[j].key = isolate()->heap()->empty_string(); |
443 secondary_[j].map = NULL; | 445 secondary_[j].map = NULL; |
444 secondary_[j].value = empty; | 446 secondary_[j].value = empty; |
445 } | 447 } |
446 } | 448 } |
447 | 449 |
448 | 450 |
449 void StubCache::CollectMatchingMaps(SmallMapList* types, | 451 void StubCache::CollectMatchingMaps(SmallMapList* types, |
450 Handle<Name> name, | 452 Handle<Name> name, |
451 Code::Flags flags, | 453 Code::Flags flags, |
452 Handle<Context> native_context, | 454 Handle<Context> native_context, |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
518 | 520 |
519 | 521 |
520 /** | 522 /** |
521 * Attempts to load a property with an interceptor (which must be present), | 523 * Attempts to load a property with an interceptor (which must be present), |
522 * but doesn't search the prototype chain. | 524 * but doesn't search the prototype chain. |
523 * | 525 * |
524 * Returns |Heap::no_interceptor_result_sentinel()| if interceptor doesn't | 526 * Returns |Heap::no_interceptor_result_sentinel()| if interceptor doesn't |
525 * provide any value for the given name. | 527 * provide any value for the given name. |
526 */ | 528 */ |
527 RUNTIME_FUNCTION(LoadPropertyWithInterceptorOnly) { | 529 RUNTIME_FUNCTION(LoadPropertyWithInterceptorOnly) { |
528 ASSERT(args.length() == StubCache::kInterceptorArgsLength); | 530 ASSERT(args.length() == NamedLoadHandlerCompiler::kInterceptorArgsLength); |
529 Handle<Name> name_handle = | 531 Handle<Name> name_handle = |
530 args.at<Name>(StubCache::kInterceptorArgsNameIndex); | 532 args.at<Name>(NamedLoadHandlerCompiler::kInterceptorArgsNameIndex); |
531 Handle<InterceptorInfo> interceptor_info = | 533 Handle<InterceptorInfo> interceptor_info = args.at<InterceptorInfo>( |
532 args.at<InterceptorInfo>(StubCache::kInterceptorArgsInfoIndex); | 534 NamedLoadHandlerCompiler::kInterceptorArgsInfoIndex); |
533 | 535 |
534 // TODO(rossberg): Support symbols in the API. | 536 // TODO(rossberg): Support symbols in the API. |
535 if (name_handle->IsSymbol()) | 537 if (name_handle->IsSymbol()) |
536 return isolate->heap()->no_interceptor_result_sentinel(); | 538 return isolate->heap()->no_interceptor_result_sentinel(); |
537 Handle<String> name = Handle<String>::cast(name_handle); | 539 Handle<String> name = Handle<String>::cast(name_handle); |
538 | 540 |
539 Address getter_address = v8::ToCData<Address>(interceptor_info->getter()); | 541 Address getter_address = v8::ToCData<Address>(interceptor_info->getter()); |
540 v8::NamedPropertyGetterCallback getter = | 542 v8::NamedPropertyGetterCallback getter = |
541 FUNCTION_CAST<v8::NamedPropertyGetterCallback>(getter_address); | 543 FUNCTION_CAST<v8::NamedPropertyGetterCallback>(getter_address); |
542 ASSERT(getter != NULL); | 544 ASSERT(getter != NULL); |
543 | 545 |
544 Handle<JSObject> receiver = | 546 Handle<JSObject> receiver = |
545 args.at<JSObject>(StubCache::kInterceptorArgsThisIndex); | 547 args.at<JSObject>(NamedLoadHandlerCompiler::kInterceptorArgsThisIndex); |
546 Handle<JSObject> holder = | 548 Handle<JSObject> holder = |
547 args.at<JSObject>(StubCache::kInterceptorArgsHolderIndex); | 549 args.at<JSObject>(NamedLoadHandlerCompiler::kInterceptorArgsHolderIndex); |
548 PropertyCallbackArguments callback_args( | 550 PropertyCallbackArguments callback_args( |
549 isolate, interceptor_info->data(), *receiver, *holder); | 551 isolate, interceptor_info->data(), *receiver, *holder); |
550 { | 552 { |
551 // Use the interceptor getter. | 553 // Use the interceptor getter. |
552 HandleScope scope(isolate); | 554 HandleScope scope(isolate); |
553 v8::Handle<v8::Value> r = | 555 v8::Handle<v8::Value> r = |
554 callback_args.Call(getter, v8::Utils::ToLocal(name)); | 556 callback_args.Call(getter, v8::Utils::ToLocal(name)); |
555 RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate); | 557 RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate); |
556 if (!r.IsEmpty()) { | 558 if (!r.IsEmpty()) { |
557 Handle<Object> result = v8::Utils::OpenHandle(*r); | 559 Handle<Object> result = v8::Utils::OpenHandle(*r); |
(...skipping 23 matching lines...) Expand all Loading... |
581 return isolate->Throw(*error); | 583 return isolate->Throw(*error); |
582 } | 584 } |
583 | 585 |
584 | 586 |
585 /** | 587 /** |
586 * Loads a property with an interceptor performing post interceptor | 588 * Loads a property with an interceptor performing post interceptor |
587 * lookup if interceptor failed. | 589 * lookup if interceptor failed. |
588 */ | 590 */ |
589 RUNTIME_FUNCTION(LoadPropertyWithInterceptor) { | 591 RUNTIME_FUNCTION(LoadPropertyWithInterceptor) { |
590 HandleScope scope(isolate); | 592 HandleScope scope(isolate); |
591 ASSERT(args.length() == StubCache::kInterceptorArgsLength); | 593 ASSERT(args.length() == NamedLoadHandlerCompiler::kInterceptorArgsLength); |
592 Handle<Name> name = | 594 Handle<Name> name = |
593 args.at<Name>(StubCache::kInterceptorArgsNameIndex); | 595 args.at<Name>(NamedLoadHandlerCompiler::kInterceptorArgsNameIndex); |
594 Handle<JSObject> receiver = | 596 Handle<JSObject> receiver = |
595 args.at<JSObject>(StubCache::kInterceptorArgsThisIndex); | 597 args.at<JSObject>(NamedLoadHandlerCompiler::kInterceptorArgsThisIndex); |
596 Handle<JSObject> holder = | 598 Handle<JSObject> holder = |
597 args.at<JSObject>(StubCache::kInterceptorArgsHolderIndex); | 599 args.at<JSObject>(NamedLoadHandlerCompiler::kInterceptorArgsHolderIndex); |
598 | 600 |
599 Handle<Object> result; | 601 Handle<Object> result; |
600 LookupIterator it(receiver, name, holder); | 602 LookupIterator it(receiver, name, holder); |
601 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( | 603 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( |
602 isolate, result, JSObject::GetProperty(&it)); | 604 isolate, result, JSObject::GetProperty(&it)); |
603 | 605 |
604 if (it.IsFound()) return *result; | 606 if (it.IsFound()) return *result; |
605 | 607 |
606 return ThrowReferenceError(isolate, Name::cast(args[0])); | 608 return ThrowReferenceError(isolate, Name::cast(args[0])); |
607 } | 609 } |
(...skipping 747 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1355 Handle<FunctionTemplateInfo>( | 1357 Handle<FunctionTemplateInfo>( |
1356 FunctionTemplateInfo::cast(signature->receiver())); | 1358 FunctionTemplateInfo::cast(signature->receiver())); |
1357 } | 1359 } |
1358 } | 1360 } |
1359 | 1361 |
1360 is_simple_api_call_ = true; | 1362 is_simple_api_call_ = true; |
1361 } | 1363 } |
1362 | 1364 |
1363 | 1365 |
1364 } } // namespace v8::internal | 1366 } } // namespace v8::internal |
OLD | NEW |