OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
93 | 93 |
94 // Update primary cache. | 94 // Update primary cache. |
95 primary->key = name; | 95 primary->key = name; |
96 primary->value = code; | 96 primary->value = code; |
97 primary->map = map; | 97 primary->map = map; |
98 isolate()->counters()->megamorphic_stub_cache_updates()->Increment(); | 98 isolate()->counters()->megamorphic_stub_cache_updates()->Increment(); |
99 return code; | 99 return code; |
100 } | 100 } |
101 | 101 |
102 | 102 |
| 103 Handle<JSObject> StubCache::StubHolder(Handle<JSObject> receiver, |
| 104 Handle<JSObject> holder) { |
| 105 InlineCacheHolderFlag cache_holder = |
| 106 IC::GetCodeCacheForObject(*receiver, *holder); |
| 107 return Handle<JSObject>(IC::GetCodeCacheHolder( |
| 108 isolate_, *receiver, cache_holder)); |
| 109 } |
| 110 |
| 111 |
| 112 Handle<Code> StubCache::FindStub(Handle<String> name, |
| 113 Handle<JSObject> stub_holder, |
| 114 Code::Kind kind, |
| 115 Code::StubType type, |
| 116 Code::IcFragment fragment) { |
| 117 Code::Flags flags = Code::ComputeMonomorphicFlags(kind, fragment, type); |
| 118 Handle<Object> probe(stub_holder->map()->FindInCodeCache(*name, flags), |
| 119 isolate_); |
| 120 if (probe->IsCode()) return Handle<Code>::cast(probe); |
| 121 return Handle<Code>::null(); |
| 122 } |
| 123 |
| 124 |
| 125 Handle<Code> StubCache::FindHandler(Handle<String> name, |
| 126 Handle<JSObject> handler_holder, |
| 127 Code::Kind kind, |
| 128 Code::StubType type) { |
| 129 return FindStub(name, handler_holder, kind, type, Code::HANDLER_FRAGMENT); |
| 130 } |
| 131 |
| 132 |
| 133 Handle<Code> StubCache::ComputeMonomorphicIC(Handle<JSObject> receiver, |
| 134 Handle<Code> handler, |
| 135 Handle<String> name) { |
| 136 Handle<Code> ic = FindStub(name, receiver, Code::LOAD_IC, |
| 137 handler->type(), Code::IC_FRAGMENT); |
| 138 if (!ic.is_null()) return ic; |
| 139 |
| 140 LoadStubCompiler ic_compiler(isolate()); |
| 141 ic = ic_compiler.CompileMonomorphicIC( |
| 142 Handle<Map>(receiver->map()), handler, name); |
| 143 |
| 144 JSObject::UpdateMapCodeCache(receiver, name, ic); |
| 145 return ic; |
| 146 } |
| 147 |
| 148 |
| 149 Handle<Code> StubCache::ComputeKeyedMonomorphicIC(Handle<JSObject> receiver, |
| 150 Handle<Code> handler, |
| 151 Handle<String> name) { |
| 152 Handle<Code> ic = FindStub(name, receiver, Code::KEYED_LOAD_IC, |
| 153 handler->type(), Code::IC_FRAGMENT); |
| 154 if (!ic.is_null()) return ic; |
| 155 |
| 156 KeyedLoadStubCompiler ic_compiler(isolate()); |
| 157 ic = ic_compiler.CompileMonomorphicIC( |
| 158 Handle<Map>(receiver->map()), handler, name); |
| 159 |
| 160 JSObject::UpdateMapCodeCache(receiver, name, ic); |
| 161 return ic; |
| 162 } |
| 163 |
| 164 |
103 Handle<Code> StubCache::ComputeLoadNonexistent(Handle<String> name, | 165 Handle<Code> StubCache::ComputeLoadNonexistent(Handle<String> name, |
104 Handle<JSObject> receiver) { | 166 Handle<JSObject> receiver) { |
105 // If no global objects are present in the prototype chain, the load | 167 // If no global objects are present in the prototype chain, the load |
106 // nonexistent IC stub can be shared for all names for a given map | 168 // nonexistent IC stub can be shared for all names for a given map |
107 // and we use the empty string for the map cache in that case. If | 169 // and we use the empty string for the map cache in that case. If |
108 // there are global objects involved, we need to check global | 170 // there are global objects involved, we need to check global |
109 // property cells in the stub and therefore the stub will be | 171 // property cells in the stub and therefore the stub will be |
110 // specific to the name. | 172 // specific to the name. |
111 Handle<String> cache_name = factory()->empty_string(); | 173 Handle<String> cache_name = factory()->empty_string(); |
112 Handle<JSObject> current; | 174 Handle<JSObject> current; |
113 Handle<Object> next = receiver; | 175 Handle<Object> next = receiver; |
114 Handle<GlobalObject> global; | 176 Handle<GlobalObject> global; |
115 do { | 177 do { |
116 current = Handle<JSObject>::cast(next); | 178 current = Handle<JSObject>::cast(next); |
117 next = Handle<Object>(current->GetPrototype(), isolate_); | 179 next = Handle<Object>(current->GetPrototype(), isolate_); |
118 if (current->IsGlobalObject()) { | 180 if (current->IsGlobalObject()) { |
119 global = Handle<GlobalObject>::cast(current); | 181 global = Handle<GlobalObject>::cast(current); |
120 cache_name = name; | 182 cache_name = name; |
121 } else if (!current->HasFastProperties()) { | 183 } else if (!current->HasFastProperties()) { |
122 cache_name = name; | 184 cache_name = name; |
123 } | 185 } |
124 } while (!next->IsNull()); | 186 } while (!next->IsNull()); |
125 | 187 |
126 // Compile the stub that is either shared for all names or | 188 // Compile the stub that is either shared for all names or |
127 // name specific if there are global objects involved. | 189 // name specific if there are global objects involved. |
128 Code::Flags flags = Code::ComputeMonomorphicFlags( | 190 Handle<Code> handler = FindHandler( |
129 Code::LOAD_IC, Code::kNoExtraICState, Code::NONEXISTENT); | 191 cache_name, receiver, Code::LOAD_IC, Code::NONEXISTENT); |
130 Handle<Object> probe(receiver->map()->FindInCodeCache(*cache_name, flags), | 192 if (!handler.is_null()) return handler; |
131 isolate_); | |
132 if (probe->IsCode()) return Handle<Code>::cast(probe); | |
133 | 193 |
134 LoadStubCompiler compiler(isolate_); | 194 LoadStubCompiler compiler(isolate_); |
135 Handle<Code> code = | 195 handler = |
136 compiler.CompileLoadNonexistent(receiver, current, cache_name, global); | 196 compiler.CompileLoadNonexistent(receiver, current, cache_name, global); |
137 PROFILE(isolate_, CodeCreateEvent(Logger::LOAD_IC_TAG, *code, *cache_name)); | 197 JSObject::UpdateMapCodeCache(receiver, cache_name, handler); |
138 GDBJIT(AddCode(GDBJITInterface::LOAD_IC, *cache_name, *code)); | 198 return handler; |
139 JSObject::UpdateMapCodeCache(receiver, cache_name, code); | |
140 return code; | |
141 } | 199 } |
142 | 200 |
143 | 201 |
144 Handle<Code> StubCache::ComputeLoadField(Handle<String> name, | 202 Handle<Code> StubCache::ComputeLoadField(Handle<String> name, |
145 Handle<JSObject> receiver, | 203 Handle<JSObject> receiver, |
146 Handle<JSObject> holder, | 204 Handle<JSObject> holder, |
147 PropertyIndex field) { | 205 PropertyIndex field) { |
148 InlineCacheHolderFlag cache_holder = | 206 if (receiver.is_identical_to(holder)) { |
149 IC::GetCodeCacheForObject(*receiver, *holder); | 207 LoadFieldStub stub(LoadStubCompiler::receiver(), |
150 Handle<JSObject> map_holder(IC::GetCodeCacheHolder( | 208 field.is_inobject(holder), |
151 isolate_, *receiver, cache_holder)); | 209 field.translate(holder)); |
152 Code::Flags flags = Code::ComputeMonomorphicFlags( | 210 return stub.GetCode(isolate()); |
153 Code::LOAD_IC, Code::kNoExtraICState, Code::FIELD); | 211 } |
154 Handle<Object> probe(map_holder->map()->FindInCodeCache(*name, flags), | 212 |
155 isolate_); | 213 Handle<JSObject> stub_holder = StubHolder(receiver, holder); |
156 if (probe->IsCode()) return Handle<Code>::cast(probe); | 214 Handle<Code> stub = FindHandler( |
| 215 name, stub_holder, Code::LOAD_IC, Code::FIELD); |
| 216 if (!stub.is_null()) return stub; |
157 | 217 |
158 LoadStubCompiler compiler(isolate_); | 218 LoadStubCompiler compiler(isolate_); |
159 Handle<Code> code = compiler.CompileLoadField(receiver, holder, name, field); | 219 Handle<Code> handler = |
160 PROFILE(isolate_, CodeCreateEvent(Logger::LOAD_IC_TAG, *code, *name)); | 220 compiler.CompileLoadField(receiver, holder, name, field); |
161 GDBJIT(AddCode(GDBJITInterface::LOAD_IC, *name, *code)); | 221 JSObject::UpdateMapCodeCache(stub_holder, name, handler); |
162 JSObject::UpdateMapCodeCache(map_holder, name, code); | 222 return handler; |
163 return code; | |
164 } | 223 } |
165 | 224 |
166 | 225 |
167 Handle<Code> StubCache::ComputeLoadCallback( | 226 Handle<Code> StubCache::ComputeLoadCallback( |
168 Handle<String> name, | 227 Handle<String> name, |
169 Handle<JSObject> receiver, | 228 Handle<JSObject> receiver, |
170 Handle<JSObject> holder, | 229 Handle<JSObject> holder, |
171 Handle<ExecutableAccessorInfo> callback) { | 230 Handle<ExecutableAccessorInfo> callback) { |
172 ASSERT(v8::ToCData<Address>(callback->getter()) != 0); | 231 ASSERT(v8::ToCData<Address>(callback->getter()) != 0); |
173 InlineCacheHolderFlag cache_holder = | 232 Handle<JSObject> stub_holder = StubHolder(receiver, holder); |
174 IC::GetCodeCacheForObject(*receiver, *holder); | 233 Handle<Code> stub = FindHandler( |
175 Handle<JSObject> map_holder(IC::GetCodeCacheHolder( | 234 name, stub_holder, Code::LOAD_IC, Code::CALLBACKS); |
176 isolate_, *receiver, cache_holder)); | 235 if (!stub.is_null()) return stub; |
177 Code::Flags flags = Code::ComputeMonomorphicFlags( | |
178 Code::LOAD_IC, Code::kNoExtraICState, Code::CALLBACKS); | |
179 Handle<Object> probe(map_holder->map()->FindInCodeCache(*name, flags), | |
180 isolate_); | |
181 if (probe->IsCode()) return Handle<Code>::cast(probe); | |
182 | 236 |
183 LoadStubCompiler compiler(isolate_); | 237 LoadStubCompiler compiler(isolate_); |
184 Handle<Code> code = | 238 Handle<Code> handler = |
185 compiler.CompileLoadCallback(receiver, holder, name, callback); | 239 compiler.CompileLoadCallback(receiver, holder, name, callback); |
186 PROFILE(isolate_, CodeCreateEvent(Logger::LOAD_IC_TAG, *code, *name)); | 240 JSObject::UpdateMapCodeCache(stub_holder, name, handler); |
187 GDBJIT(AddCode(GDBJITInterface::LOAD_IC, *name, *code)); | 241 return handler; |
188 JSObject::UpdateMapCodeCache(map_holder, name, code); | |
189 return code; | |
190 } | 242 } |
191 | 243 |
192 | 244 |
193 Handle<Code> StubCache::ComputeLoadViaGetter(Handle<String> name, | 245 Handle<Code> StubCache::ComputeLoadViaGetter(Handle<String> name, |
194 Handle<JSObject> receiver, | 246 Handle<JSObject> receiver, |
195 Handle<JSObject> holder, | 247 Handle<JSObject> holder, |
196 Handle<JSFunction> getter) { | 248 Handle<JSFunction> getter) { |
197 InlineCacheHolderFlag cache_holder = | 249 Handle<JSObject> stub_holder = StubHolder(receiver, holder); |
198 IC::GetCodeCacheForObject(*receiver, *holder); | 250 Handle<Code> stub = FindHandler( |
199 Handle<JSObject> map_holder(IC::GetCodeCacheHolder( | 251 name, stub_holder, Code::LOAD_IC, Code::CALLBACKS); |
200 isolate_, *receiver, cache_holder)); | 252 if (!stub.is_null()) return stub; |
201 Code::Flags flags = Code::ComputeMonomorphicFlags( | |
202 Code::LOAD_IC, Code::kNoExtraICState, Code::CALLBACKS); | |
203 Handle<Object> probe(map_holder->map()->FindInCodeCache(*name, flags), | |
204 isolate_); | |
205 if (probe->IsCode()) return Handle<Code>::cast(probe); | |
206 | 253 |
207 LoadStubCompiler compiler(isolate_); | 254 LoadStubCompiler compiler(isolate_); |
208 Handle<Code> code = | 255 Handle<Code> handler = |
209 compiler.CompileLoadViaGetter(receiver, holder, name, getter); | 256 compiler.CompileLoadViaGetter(receiver, holder, name, getter); |
210 PROFILE(isolate_, CodeCreateEvent(Logger::LOAD_IC_TAG, *code, *name)); | 257 JSObject::UpdateMapCodeCache(stub_holder, name, handler); |
211 GDBJIT(AddCode(GDBJITInterface::LOAD_IC, *name, *code)); | 258 return handler; |
212 JSObject::UpdateMapCodeCache(map_holder, name, code); | |
213 return code; | |
214 } | 259 } |
215 | 260 |
216 | 261 |
217 Handle<Code> StubCache::ComputeLoadConstant(Handle<String> name, | 262 Handle<Code> StubCache::ComputeLoadConstant(Handle<String> name, |
218 Handle<JSObject> receiver, | 263 Handle<JSObject> receiver, |
219 Handle<JSObject> holder, | 264 Handle<JSObject> holder, |
220 Handle<JSFunction> value) { | 265 Handle<JSFunction> value) { |
221 InlineCacheHolderFlag cache_holder = | 266 Handle<JSObject> stub_holder = StubHolder(receiver, holder); |
222 IC::GetCodeCacheForObject(*receiver, *holder); | 267 Handle<Code> handler = FindHandler( |
223 Handle<JSObject> map_holder(IC::GetCodeCacheHolder( | 268 name, stub_holder, Code::LOAD_IC, Code::CONSTANT_FUNCTION); |
224 isolate_, *receiver, cache_holder)); | 269 if (!handler.is_null()) return handler; |
225 Code::Flags flags = Code::ComputeMonomorphicFlags( | |
226 Code::LOAD_IC, Code::kNoExtraICState, Code::CONSTANT_FUNCTION); | |
227 Handle<Object> probe(map_holder->map()->FindInCodeCache(*name, flags), | |
228 isolate_); | |
229 if (probe->IsCode()) return Handle<Code>::cast(probe); | |
230 | 270 |
231 LoadStubCompiler compiler(isolate_); | 271 LoadStubCompiler compiler(isolate_); |
232 Handle<Code> code = | 272 handler = compiler.CompileLoadConstant(receiver, holder, name, value); |
233 compiler.CompileLoadConstant(receiver, holder, name, value); | 273 JSObject::UpdateMapCodeCache(stub_holder, name, handler); |
234 PROFILE(isolate_, CodeCreateEvent(Logger::LOAD_IC_TAG, *code, *name)); | 274 |
235 GDBJIT(AddCode(GDBJITInterface::LOAD_IC, *name, *code)); | 275 return handler; |
236 JSObject::UpdateMapCodeCache(map_holder, name, code); | |
237 return code; | |
238 } | 276 } |
239 | 277 |
240 | 278 |
241 Handle<Code> StubCache::ComputeLoadInterceptor(Handle<String> name, | 279 Handle<Code> StubCache::ComputeLoadInterceptor(Handle<String> name, |
242 Handle<JSObject> receiver, | 280 Handle<JSObject> receiver, |
243 Handle<JSObject> holder) { | 281 Handle<JSObject> holder) { |
244 InlineCacheHolderFlag cache_holder = | 282 Handle<JSObject> stub_holder = StubHolder(receiver, holder); |
245 IC::GetCodeCacheForObject(*receiver, *holder); | 283 Handle<Code> stub = FindHandler( |
246 Handle<JSObject> map_holder(IC::GetCodeCacheHolder( | 284 name, stub_holder, Code::LOAD_IC, Code::INTERCEPTOR); |
247 isolate_, *receiver, cache_holder)); | 285 if (!stub.is_null()) return stub; |
248 Code::Flags flags = Code::ComputeMonomorphicFlags( | |
249 Code::LOAD_IC, Code::kNoExtraICState, Code::INTERCEPTOR); | |
250 Handle<Object> probe(map_holder->map()->FindInCodeCache(*name, flags), | |
251 isolate_); | |
252 if (probe->IsCode()) return Handle<Code>::cast(probe); | |
253 | 286 |
254 LoadStubCompiler compiler(isolate_); | 287 LoadStubCompiler compiler(isolate_); |
255 Handle<Code> code = | 288 Handle<Code> handler = |
256 compiler.CompileLoadInterceptor(receiver, holder, name); | 289 compiler.CompileLoadInterceptor(receiver, holder, name); |
257 PROFILE(isolate_, CodeCreateEvent(Logger::LOAD_IC_TAG, *code, *name)); | 290 JSObject::UpdateMapCodeCache(stub_holder, name, handler); |
258 GDBJIT(AddCode(GDBJITInterface::LOAD_IC, *name, *code)); | 291 return handler; |
259 JSObject::UpdateMapCodeCache(map_holder, name, code); | |
260 return code; | |
261 } | 292 } |
262 | 293 |
263 | 294 |
264 Handle<Code> StubCache::ComputeLoadNormal() { | 295 Handle<Code> StubCache::ComputeLoadNormal(Handle<String> name, |
| 296 Handle<JSObject> receiver) { |
265 return isolate_->builtins()->LoadIC_Normal(); | 297 return isolate_->builtins()->LoadIC_Normal(); |
266 } | 298 } |
267 | 299 |
268 | 300 |
269 Handle<Code> StubCache::ComputeLoadGlobal(Handle<String> name, | 301 Handle<Code> StubCache::ComputeLoadGlobal(Handle<String> name, |
270 Handle<JSObject> receiver, | 302 Handle<JSObject> receiver, |
271 Handle<GlobalObject> holder, | 303 Handle<GlobalObject> holder, |
272 Handle<JSGlobalPropertyCell> cell, | 304 Handle<JSGlobalPropertyCell> cell, |
273 bool is_dont_delete) { | 305 bool is_dont_delete) { |
274 InlineCacheHolderFlag cache_holder = | 306 Handle<JSObject> stub_holder = StubHolder(receiver, holder); |
275 IC::GetCodeCacheForObject(*receiver, *holder); | 307 Handle<Code> stub = FindStub( |
276 Handle<JSObject> map_holder(IC::GetCodeCacheHolder( | 308 name, stub_holder, Code::LOAD_IC, Code::NORMAL, Code::IC_FRAGMENT); |
277 isolate_, *receiver, cache_holder)); | 309 if (!stub.is_null()) return stub; |
278 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::LOAD_IC); | |
279 Handle<Object> probe(map_holder->map()->FindInCodeCache(*name, flags), | |
280 isolate_); | |
281 if (probe->IsCode()) return Handle<Code>::cast(probe); | |
282 | 310 |
283 LoadStubCompiler compiler(isolate_); | 311 LoadStubCompiler compiler(isolate_); |
284 Handle<Code> code = | 312 Handle<Code> ic = |
285 compiler.CompileLoadGlobal(receiver, holder, cell, name, is_dont_delete); | 313 compiler.CompileLoadGlobal(receiver, holder, cell, name, is_dont_delete); |
286 PROFILE(isolate_, CodeCreateEvent(Logger::LOAD_IC_TAG, *code, *name)); | 314 JSObject::UpdateMapCodeCache(stub_holder, name, ic); |
287 GDBJIT(AddCode(GDBJITInterface::LOAD_IC, *name, *code)); | 315 return ic; |
288 JSObject::UpdateMapCodeCache(map_holder, name, code); | |
289 return code; | |
290 } | 316 } |
291 | 317 |
292 | 318 |
293 Handle<Code> StubCache::ComputeKeyedLoadField(Handle<String> name, | 319 Handle<Code> StubCache::ComputeKeyedLoadField(Handle<String> name, |
294 Handle<JSObject> receiver, | 320 Handle<JSObject> receiver, |
295 Handle<JSObject> holder, | 321 Handle<JSObject> holder, |
296 PropertyIndex field) { | 322 PropertyIndex field) { |
297 InlineCacheHolderFlag cache_holder = | 323 if (receiver.is_identical_to(holder)) { |
298 IC::GetCodeCacheForObject(*receiver, *holder); | 324 LoadFieldStub stub(KeyedLoadStubCompiler::receiver(), |
299 Handle<JSObject> map_holder(IC::GetCodeCacheHolder( | 325 field.is_inobject(holder), |
300 isolate_, *receiver, cache_holder)); | 326 field.translate(holder)); |
301 Code::Flags flags = Code::ComputeMonomorphicFlags( | 327 return stub.GetCode(isolate()); |
302 Code::KEYED_LOAD_IC, Code::kNoExtraICState, Code::FIELD); | 328 } |
303 Handle<Object> probe(map_holder->map()->FindInCodeCache(*name, flags), | 329 |
304 isolate_); | 330 Handle<JSObject> stub_holder = StubHolder(receiver, holder); |
305 if (probe->IsCode()) return Handle<Code>::cast(probe); | 331 Handle<Code> stub = FindHandler( |
| 332 name, stub_holder, Code::KEYED_LOAD_IC, Code::FIELD); |
| 333 if (!stub.is_null()) return stub; |
306 | 334 |
307 KeyedLoadStubCompiler compiler(isolate_); | 335 KeyedLoadStubCompiler compiler(isolate_); |
308 Handle<Code> code = compiler.CompileLoadField(receiver, holder, name, field); | 336 Handle<Code> handler = |
309 PROFILE(isolate_, CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, *code, *name)); | 337 compiler.CompileLoadField(receiver, holder, name, field); |
310 GDBJIT(AddCode(GDBJITInterface::KEYED_LOAD_IC, *name, *code)); | 338 JSObject::UpdateMapCodeCache(stub_holder, name, handler); |
311 JSObject::UpdateMapCodeCache(map_holder, name, code); | 339 return handler; |
312 return code; | |
313 } | 340 } |
314 | 341 |
315 | 342 |
316 Handle<Code> StubCache::ComputeKeyedLoadConstant(Handle<String> name, | 343 Handle<Code> StubCache::ComputeKeyedLoadConstant(Handle<String> name, |
317 Handle<JSObject> receiver, | 344 Handle<JSObject> receiver, |
318 Handle<JSObject> holder, | 345 Handle<JSObject> holder, |
319 Handle<JSFunction> value) { | 346 Handle<JSFunction> value) { |
320 InlineCacheHolderFlag cache_holder = | 347 Handle<JSObject> stub_holder = StubHolder(receiver, holder); |
321 IC::GetCodeCacheForObject(*receiver, *holder); | 348 Handle<Code> handler = FindHandler( |
322 Handle<JSObject> map_holder(IC::GetCodeCacheHolder( | 349 name, stub_holder, Code::KEYED_LOAD_IC, Code::CONSTANT_FUNCTION); |
323 isolate_, *receiver, cache_holder)); | 350 if (!handler.is_null()) return handler; |
324 Code::Flags flags = Code::ComputeMonomorphicFlags( | |
325 Code::KEYED_LOAD_IC, Code::kNoExtraICState, Code::CONSTANT_FUNCTION); | |
326 Handle<Object> probe(map_holder->map()->FindInCodeCache(*name, flags), | |
327 isolate_); | |
328 if (probe->IsCode()) return Handle<Code>::cast(probe); | |
329 | 351 |
330 KeyedLoadStubCompiler compiler(isolate_); | 352 KeyedLoadStubCompiler compiler(isolate_); |
331 Handle<Code> code = | 353 handler = compiler.CompileLoadConstant(receiver, holder, name, value); |
332 compiler.CompileLoadConstant(receiver, holder, name, value); | 354 JSObject::UpdateMapCodeCache(stub_holder, name, handler); |
333 PROFILE(isolate_, CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, *code, *name)); | 355 return handler; |
334 GDBJIT(AddCode(GDBJITInterface::KEYED_LOAD_IC, *name, *code)); | |
335 JSObject::UpdateMapCodeCache(map_holder, name, code); | |
336 return code; | |
337 } | 356 } |
338 | 357 |
339 | 358 |
340 Handle<Code> StubCache::ComputeKeyedLoadInterceptor(Handle<String> name, | 359 Handle<Code> StubCache::ComputeKeyedLoadInterceptor(Handle<String> name, |
341 Handle<JSObject> receiver, | 360 Handle<JSObject> receiver, |
342 Handle<JSObject> holder) { | 361 Handle<JSObject> holder) { |
343 InlineCacheHolderFlag cache_holder = | 362 Handle<JSObject> stub_holder = StubHolder(receiver, holder); |
344 IC::GetCodeCacheForObject(*receiver, *holder); | 363 Handle<Code> stub = FindHandler( |
345 Handle<JSObject> map_holder(IC::GetCodeCacheHolder( | 364 name, stub_holder, Code::KEYED_LOAD_IC, Code::INTERCEPTOR); |
346 isolate_, *receiver, cache_holder)); | 365 if (!stub.is_null()) return stub; |
347 Code::Flags flags = Code::ComputeMonomorphicFlags( | |
348 Code::KEYED_LOAD_IC, Code::kNoExtraICState, Code::INTERCEPTOR); | |
349 Handle<Object> probe(map_holder->map()->FindInCodeCache(*name, flags), | |
350 isolate_); | |
351 if (probe->IsCode()) return Handle<Code>::cast(probe); | |
352 | 366 |
353 KeyedLoadStubCompiler compiler(isolate_); | 367 KeyedLoadStubCompiler compiler(isolate_); |
354 Handle<Code> code = compiler.CompileLoadInterceptor(receiver, holder, name); | 368 Handle<Code> handler = |
355 PROFILE(isolate_, CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, *code, *name)); | 369 compiler.CompileLoadInterceptor(receiver, holder, name); |
356 GDBJIT(AddCode(GDBJITInterface::KEYED_LOAD_IC, *name, *code)); | 370 JSObject::UpdateMapCodeCache(stub_holder, name, handler); |
357 JSObject::UpdateMapCodeCache(map_holder, name, code); | 371 return handler; |
358 return code; | |
359 } | 372 } |
360 | 373 |
361 | 374 |
362 Handle<Code> StubCache::ComputeKeyedLoadCallback( | 375 Handle<Code> StubCache::ComputeKeyedLoadCallback( |
363 Handle<String> name, | 376 Handle<String> name, |
364 Handle<JSObject> receiver, | 377 Handle<JSObject> receiver, |
365 Handle<JSObject> holder, | 378 Handle<JSObject> holder, |
366 Handle<ExecutableAccessorInfo> callback) { | 379 Handle<ExecutableAccessorInfo> callback) { |
367 InlineCacheHolderFlag cache_holder = | 380 Handle<JSObject> stub_holder = StubHolder(receiver, holder); |
368 IC::GetCodeCacheForObject(*receiver, *holder); | 381 Handle<Code> stub = FindHandler( |
369 Handle<JSObject> map_holder(IC::GetCodeCacheHolder( | 382 name, stub_holder, Code::KEYED_LOAD_IC, Code::CALLBACKS); |
370 isolate_, *receiver, cache_holder)); | 383 if (!stub.is_null()) return stub; |
371 Code::Flags flags = Code::ComputeMonomorphicFlags( | |
372 Code::KEYED_LOAD_IC, Code::kNoExtraICState, Code::CALLBACKS); | |
373 Handle<Object> probe(map_holder->map()->FindInCodeCache(*name, flags), | |
374 isolate_); | |
375 if (probe->IsCode()) return Handle<Code>::cast(probe); | |
376 | 384 |
377 KeyedLoadStubCompiler compiler(isolate_); | 385 KeyedLoadStubCompiler compiler(isolate_); |
378 Handle<Code> code = | 386 Handle<Code> handler = |
379 compiler.CompileLoadCallback(receiver, holder, name, callback); | 387 compiler.CompileLoadCallback(receiver, holder, name, callback); |
380 PROFILE(isolate_, CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, *code, *name)); | 388 JSObject::UpdateMapCodeCache(stub_holder, name, handler); |
381 GDBJIT(AddCode(GDBJITInterface::KEYED_LOAD_IC, *name, *code)); | 389 return handler; |
382 JSObject::UpdateMapCodeCache(map_holder, name, code); | |
383 return code; | |
384 } | 390 } |
385 | 391 |
386 | 392 |
387 Handle<Code> StubCache::ComputeStoreField(Handle<String> name, | 393 Handle<Code> StubCache::ComputeStoreField(Handle<String> name, |
388 Handle<JSObject> receiver, | 394 Handle<JSObject> receiver, |
389 int field_index, | 395 int field_index, |
390 Handle<Map> transition, | 396 Handle<Map> transition, |
391 StrictModeFlag strict_mode) { | 397 StrictModeFlag strict_mode) { |
392 Code::StubType type = | 398 Code::StubType type = |
393 (transition.is_null()) ? Code::FIELD : Code::MAP_TRANSITION; | 399 (transition.is_null()) ? Code::FIELD : Code::MAP_TRANSITION; |
394 Code::Flags flags = Code::ComputeMonomorphicFlags( | 400 Code::Flags flags = Code::ComputeMonomorphicFlags( |
395 Code::STORE_IC, strict_mode, type); | 401 Code::STORE_IC, strict_mode, type); |
396 Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags), | 402 Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags), |
397 isolate_); | 403 isolate_); |
398 if (probe->IsCode()) return Handle<Code>::cast(probe); | 404 if (probe->IsCode()) return Handle<Code>::cast(probe); |
399 | 405 |
400 StoreStubCompiler compiler(isolate_, strict_mode); | 406 StoreStubCompiler compiler(isolate_, strict_mode); |
401 Handle<Code> code = | 407 Handle<Code> code = |
402 compiler.CompileStoreField(receiver, field_index, transition, name); | 408 compiler.CompileStoreField(receiver, field_index, transition, name); |
403 PROFILE(isolate_, CodeCreateEvent(Logger::STORE_IC_TAG, *code, *name)); | |
404 GDBJIT(AddCode(GDBJITInterface::STORE_IC, *name, *code)); | |
405 JSObject::UpdateMapCodeCache(receiver, name, code); | 409 JSObject::UpdateMapCodeCache(receiver, name, code); |
406 return code; | 410 return code; |
407 } | 411 } |
408 | 412 |
409 | 413 |
410 Handle<Code> StubCache::ComputeKeyedLoadElement(Handle<Map> receiver_map) { | 414 Handle<Code> StubCache::ComputeKeyedLoadElement(Handle<Map> receiver_map) { |
411 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC); | 415 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC); |
412 Handle<String> name = | 416 Handle<String> name = |
413 isolate()->factory()->KeyedLoadElementMonomorphic_string(); | 417 isolate()->factory()->KeyedLoadElementMonomorphic_string(); |
414 | 418 |
415 Handle<Object> probe(receiver_map->FindInCodeCache(*name, flags), isolate_); | 419 Handle<Object> probe(receiver_map->FindInCodeCache(*name, flags), isolate_); |
416 if (probe->IsCode()) return Handle<Code>::cast(probe); | 420 if (probe->IsCode()) return Handle<Code>::cast(probe); |
417 | 421 |
418 KeyedLoadStubCompiler compiler(isolate()); | 422 KeyedLoadStubCompiler compiler(isolate()); |
419 Handle<Code> code = compiler.CompileLoadElement(receiver_map); | 423 Handle<Code> code = compiler.CompileLoadElement(receiver_map); |
420 | 424 |
421 PROFILE(isolate(), CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, *code, 0)); | |
422 Map::UpdateCodeCache(receiver_map, name, code); | 425 Map::UpdateCodeCache(receiver_map, name, code); |
423 return code; | 426 return code; |
424 } | 427 } |
425 | 428 |
426 | 429 |
427 Handle<Code> StubCache::ComputeKeyedStoreElement( | 430 Handle<Code> StubCache::ComputeKeyedStoreElement( |
428 Handle<Map> receiver_map, | 431 Handle<Map> receiver_map, |
429 KeyedStoreIC::StubKind stub_kind, | 432 KeyedStoreIC::StubKind stub_kind, |
430 StrictModeFlag strict_mode, | 433 StrictModeFlag strict_mode, |
431 KeyedAccessGrowMode grow_mode) { | 434 KeyedAccessGrowMode grow_mode) { |
432 Code::ExtraICState extra_state = | 435 Code::ExtraICState extra_state = |
433 Code::ComputeExtraICState(grow_mode, strict_mode); | 436 Code::ComputeExtraICState(grow_mode, strict_mode); |
434 Code::Flags flags = Code::ComputeMonomorphicFlags( | 437 Code::Flags flags = Code::ComputeMonomorphicFlags( |
435 Code::KEYED_STORE_IC, extra_state); | 438 Code::KEYED_STORE_IC, extra_state); |
436 | 439 |
437 ASSERT(stub_kind == KeyedStoreIC::STORE_NO_TRANSITION || | 440 ASSERT(stub_kind == KeyedStoreIC::STORE_NO_TRANSITION || |
438 stub_kind == KeyedStoreIC::STORE_AND_GROW_NO_TRANSITION); | 441 stub_kind == KeyedStoreIC::STORE_AND_GROW_NO_TRANSITION); |
439 | 442 |
440 Handle<String> name = stub_kind == KeyedStoreIC::STORE_NO_TRANSITION | 443 Handle<String> name = stub_kind == KeyedStoreIC::STORE_NO_TRANSITION |
441 ? isolate()->factory()->KeyedStoreElementMonomorphic_string() | 444 ? isolate()->factory()->KeyedStoreElementMonomorphic_string() |
442 : isolate()->factory()->KeyedStoreAndGrowElementMonomorphic_string(); | 445 : isolate()->factory()->KeyedStoreAndGrowElementMonomorphic_string(); |
443 | 446 |
444 Handle<Object> probe(receiver_map->FindInCodeCache(*name, flags), isolate_); | 447 Handle<Object> probe(receiver_map->FindInCodeCache(*name, flags), isolate_); |
445 if (probe->IsCode()) return Handle<Code>::cast(probe); | 448 if (probe->IsCode()) return Handle<Code>::cast(probe); |
446 | 449 |
447 KeyedStoreStubCompiler compiler(isolate(), strict_mode, grow_mode); | 450 KeyedStoreStubCompiler compiler(isolate(), strict_mode, grow_mode); |
448 Handle<Code> code = compiler.CompileStoreElement(receiver_map); | 451 Handle<Code> code = compiler.CompileStoreElement(receiver_map); |
449 | 452 |
450 PROFILE(isolate(), CodeCreateEvent(Logger::KEYED_STORE_IC_TAG, *code, 0)); | |
451 Map::UpdateCodeCache(receiver_map, name, code); | 453 Map::UpdateCodeCache(receiver_map, name, code); |
452 return code; | 454 return code; |
453 } | 455 } |
454 | 456 |
455 | 457 |
456 Handle<Code> StubCache::ComputeStoreNormal(StrictModeFlag strict_mode) { | 458 Handle<Code> StubCache::ComputeStoreNormal(StrictModeFlag strict_mode) { |
457 return (strict_mode == kStrictMode) | 459 return (strict_mode == kStrictMode) |
458 ? isolate_->builtins()->Builtins::StoreIC_Normal_Strict() | 460 ? isolate_->builtins()->Builtins::StoreIC_Normal_Strict() |
459 : isolate_->builtins()->Builtins::StoreIC_Normal(); | 461 : isolate_->builtins()->Builtins::StoreIC_Normal(); |
460 } | 462 } |
461 | 463 |
462 | 464 |
463 Handle<Code> StubCache::ComputeStoreGlobal(Handle<String> name, | 465 Handle<Code> StubCache::ComputeStoreGlobal(Handle<String> name, |
464 Handle<GlobalObject> receiver, | 466 Handle<GlobalObject> receiver, |
465 Handle<JSGlobalPropertyCell> cell, | 467 Handle<JSGlobalPropertyCell> cell, |
466 StrictModeFlag strict_mode) { | 468 StrictModeFlag strict_mode) { |
467 Code::Flags flags = Code::ComputeMonomorphicFlags( | 469 Code::Flags flags = Code::ComputeMonomorphicFlags( |
468 Code::STORE_IC, strict_mode); | 470 Code::STORE_IC, strict_mode); |
469 Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags), | 471 Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags), |
470 isolate_); | 472 isolate_); |
471 if (probe->IsCode()) return Handle<Code>::cast(probe); | 473 if (probe->IsCode()) return Handle<Code>::cast(probe); |
472 | 474 |
473 StoreStubCompiler compiler(isolate_, strict_mode); | 475 StoreStubCompiler compiler(isolate_, strict_mode); |
474 Handle<Code> code = compiler.CompileStoreGlobal(receiver, cell, name); | 476 Handle<Code> code = compiler.CompileStoreGlobal(receiver, cell, name); |
475 PROFILE(isolate_, CodeCreateEvent(Logger::STORE_IC_TAG, *code, *name)); | |
476 GDBJIT(AddCode(GDBJITInterface::STORE_IC, *name, *code)); | |
477 JSObject::UpdateMapCodeCache(receiver, name, code); | 477 JSObject::UpdateMapCodeCache(receiver, name, code); |
478 return code; | 478 return code; |
479 } | 479 } |
480 | 480 |
481 | 481 |
482 Handle<Code> StubCache::ComputeStoreCallback( | 482 Handle<Code> StubCache::ComputeStoreCallback( |
483 Handle<String> name, | 483 Handle<String> name, |
484 Handle<JSObject> receiver, | 484 Handle<JSObject> receiver, |
485 Handle<JSObject> holder, | 485 Handle<JSObject> holder, |
486 Handle<ExecutableAccessorInfo> callback, | 486 Handle<ExecutableAccessorInfo> callback, |
487 StrictModeFlag strict_mode) { | 487 StrictModeFlag strict_mode) { |
488 ASSERT(v8::ToCData<Address>(callback->setter()) != 0); | 488 ASSERT(v8::ToCData<Address>(callback->setter()) != 0); |
489 Code::Flags flags = Code::ComputeMonomorphicFlags( | 489 Code::Flags flags = Code::ComputeMonomorphicFlags( |
490 Code::STORE_IC, strict_mode, Code::CALLBACKS); | 490 Code::STORE_IC, strict_mode, Code::CALLBACKS); |
491 Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags), | 491 Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags), |
492 isolate_); | 492 isolate_); |
493 if (probe->IsCode()) return Handle<Code>::cast(probe); | 493 if (probe->IsCode()) return Handle<Code>::cast(probe); |
494 | 494 |
495 StoreStubCompiler compiler(isolate_, strict_mode); | 495 StoreStubCompiler compiler(isolate_, strict_mode); |
496 Handle<Code> code = | 496 Handle<Code> code = |
497 compiler.CompileStoreCallback(name, receiver, holder, callback); | 497 compiler.CompileStoreCallback(name, receiver, holder, callback); |
498 PROFILE(isolate_, CodeCreateEvent(Logger::STORE_IC_TAG, *code, *name)); | |
499 GDBJIT(AddCode(GDBJITInterface::STORE_IC, *name, *code)); | |
500 JSObject::UpdateMapCodeCache(receiver, name, code); | 498 JSObject::UpdateMapCodeCache(receiver, name, code); |
501 return code; | 499 return code; |
502 } | 500 } |
503 | 501 |
504 | 502 |
505 Handle<Code> StubCache::ComputeStoreViaSetter(Handle<String> name, | 503 Handle<Code> StubCache::ComputeStoreViaSetter(Handle<String> name, |
506 Handle<JSObject> receiver, | 504 Handle<JSObject> receiver, |
507 Handle<JSObject> holder, | 505 Handle<JSObject> holder, |
508 Handle<JSFunction> setter, | 506 Handle<JSFunction> setter, |
509 StrictModeFlag strict_mode) { | 507 StrictModeFlag strict_mode) { |
510 Code::Flags flags = Code::ComputeMonomorphicFlags( | 508 Code::Flags flags = Code::ComputeMonomorphicFlags( |
511 Code::STORE_IC, strict_mode, Code::CALLBACKS); | 509 Code::STORE_IC, strict_mode, Code::CALLBACKS); |
512 Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags), | 510 Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags), |
513 isolate_); | 511 isolate_); |
514 if (probe->IsCode()) return Handle<Code>::cast(probe); | 512 if (probe->IsCode()) return Handle<Code>::cast(probe); |
515 | 513 |
516 StoreStubCompiler compiler(isolate_, strict_mode); | 514 StoreStubCompiler compiler(isolate_, strict_mode); |
517 Handle<Code> code = | 515 Handle<Code> code = |
518 compiler.CompileStoreViaSetter(name, receiver, holder, setter); | 516 compiler.CompileStoreViaSetter(name, receiver, holder, setter); |
519 PROFILE(isolate_, CodeCreateEvent(Logger::STORE_IC_TAG, *code, *name)); | |
520 GDBJIT(AddCode(GDBJITInterface::STORE_IC, *name, *code)); | |
521 JSObject::UpdateMapCodeCache(receiver, name, code); | 517 JSObject::UpdateMapCodeCache(receiver, name, code); |
522 return code; | 518 return code; |
523 } | 519 } |
524 | 520 |
525 | 521 |
526 Handle<Code> StubCache::ComputeStoreInterceptor(Handle<String> name, | 522 Handle<Code> StubCache::ComputeStoreInterceptor(Handle<String> name, |
527 Handle<JSObject> receiver, | 523 Handle<JSObject> receiver, |
528 StrictModeFlag strict_mode) { | 524 StrictModeFlag strict_mode) { |
529 Code::Flags flags = Code::ComputeMonomorphicFlags( | 525 Code::Flags flags = Code::ComputeMonomorphicFlags( |
530 Code::STORE_IC, strict_mode, Code::INTERCEPTOR); | 526 Code::STORE_IC, strict_mode, Code::INTERCEPTOR); |
531 Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags), | 527 Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags), |
532 isolate_); | 528 isolate_); |
533 if (probe->IsCode()) return Handle<Code>::cast(probe); | 529 if (probe->IsCode()) return Handle<Code>::cast(probe); |
534 | 530 |
535 StoreStubCompiler compiler(isolate_, strict_mode); | 531 StoreStubCompiler compiler(isolate_, strict_mode); |
536 Handle<Code> code = compiler.CompileStoreInterceptor(receiver, name); | 532 Handle<Code> code = compiler.CompileStoreInterceptor(receiver, name); |
537 PROFILE(isolate_, CodeCreateEvent(Logger::STORE_IC_TAG, *code, *name)); | |
538 GDBJIT(AddCode(GDBJITInterface::STORE_IC, *name, *code)); | |
539 JSObject::UpdateMapCodeCache(receiver, name, code); | 533 JSObject::UpdateMapCodeCache(receiver, name, code); |
540 return code; | 534 return code; |
541 } | 535 } |
542 | 536 |
543 Handle<Code> StubCache::ComputeKeyedStoreField(Handle<String> name, | 537 Handle<Code> StubCache::ComputeKeyedStoreField(Handle<String> name, |
544 Handle<JSObject> receiver, | 538 Handle<JSObject> receiver, |
545 int field_index, | 539 int field_index, |
546 Handle<Map> transition, | 540 Handle<Map> transition, |
547 StrictModeFlag strict_mode) { | 541 StrictModeFlag strict_mode) { |
548 Code::StubType type = | 542 Code::StubType type = |
549 (transition.is_null()) ? Code::FIELD : Code::MAP_TRANSITION; | 543 (transition.is_null()) ? Code::FIELD : Code::MAP_TRANSITION; |
550 Code::Flags flags = Code::ComputeMonomorphicFlags( | 544 Code::Flags flags = Code::ComputeMonomorphicFlags( |
551 Code::KEYED_STORE_IC, strict_mode, type); | 545 Code::KEYED_STORE_IC, strict_mode, type); |
552 Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags), | 546 Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags), |
553 isolate_); | 547 isolate_); |
554 if (probe->IsCode()) return Handle<Code>::cast(probe); | 548 if (probe->IsCode()) return Handle<Code>::cast(probe); |
555 | 549 |
556 KeyedStoreStubCompiler compiler(isolate(), strict_mode, | 550 KeyedStoreStubCompiler compiler(isolate(), strict_mode, |
557 DO_NOT_ALLOW_JSARRAY_GROWTH); | 551 DO_NOT_ALLOW_JSARRAY_GROWTH); |
558 Handle<Code> code = | 552 Handle<Code> code = |
559 compiler.CompileStoreField(receiver, field_index, transition, name); | 553 compiler.CompileStoreField(receiver, field_index, transition, name); |
560 PROFILE(isolate_, CodeCreateEvent(Logger::KEYED_STORE_IC_TAG, *code, *name)); | |
561 GDBJIT(AddCode(GDBJITInterface::KEYED_STORE_IC, *name, *code)); | |
562 JSObject::UpdateMapCodeCache(receiver, name, code); | 554 JSObject::UpdateMapCodeCache(receiver, name, code); |
563 return code; | 555 return code; |
564 } | 556 } |
565 | 557 |
566 | 558 |
567 #define CALL_LOGGER_TAG(kind, type) \ | 559 #define CALL_LOGGER_TAG(kind, type) \ |
568 (kind == Code::CALL_IC ? Logger::type : Logger::KEYED_##type) | 560 (kind == Code::CALL_IC ? Logger::type : Logger::KEYED_##type) |
569 | 561 |
570 Handle<Code> StubCache::ComputeCallConstant(int argc, | 562 Handle<Code> StubCache::ComputeCallConstant(int argc, |
571 Code::Kind kind, | 563 Code::Kind kind, |
572 Code::ExtraICState extra_state, | 564 Code::ExtraICState extra_state, |
573 Handle<String> name, | 565 Handle<String> name, |
574 Handle<Object> object, | 566 Handle<Object> object, |
575 Handle<JSObject> holder, | 567 Handle<JSObject> holder, |
576 Handle<JSFunction> function) { | 568 Handle<JSFunction> function) { |
577 // Compute the check type and the map. | 569 // Compute the check type and the map. |
578 InlineCacheHolderFlag cache_holder = | 570 InlineCacheHolderFlag cache_holder = |
579 IC::GetCodeCacheForObject(*object, *holder); | 571 IC::GetCodeCacheForObject(*object, *holder); |
580 Handle<JSObject> map_holder( | 572 Handle<JSObject> stub_holder(IC::GetCodeCacheHolder( |
581 IC::GetCodeCacheHolder(isolate_, *object, cache_holder)); | 573 isolate_, *object, cache_holder)); |
582 | 574 |
583 // Compute check type based on receiver/holder. | 575 // Compute check type based on receiver/holder. |
584 CheckType check = RECEIVER_MAP_CHECK; | 576 CheckType check = RECEIVER_MAP_CHECK; |
585 if (object->IsString()) { | 577 if (object->IsString()) { |
586 check = STRING_CHECK; | 578 check = STRING_CHECK; |
587 } else if (object->IsSymbol()) { | 579 } else if (object->IsSymbol()) { |
588 check = SYMBOL_CHECK; | 580 check = SYMBOL_CHECK; |
589 } else if (object->IsNumber()) { | 581 } else if (object->IsNumber()) { |
590 check = NUMBER_CHECK; | 582 check = NUMBER_CHECK; |
591 } else if (object->IsBoolean()) { | 583 } else if (object->IsBoolean()) { |
592 check = BOOLEAN_CHECK; | 584 check = BOOLEAN_CHECK; |
593 } | 585 } |
594 | 586 |
595 if (check != RECEIVER_MAP_CHECK && | 587 if (check != RECEIVER_MAP_CHECK && |
596 !function->IsBuiltin() && | 588 !function->IsBuiltin() && |
597 function->shared()->is_classic_mode()) { | 589 function->shared()->is_classic_mode()) { |
598 // Calling non-strict non-builtins with a value as the receiver | 590 // Calling non-strict non-builtins with a value as the receiver |
599 // requires boxing. | 591 // requires boxing. |
600 return Handle<Code>::null(); | 592 return Handle<Code>::null(); |
601 } | 593 } |
602 | 594 |
603 Code::Flags flags = Code::ComputeMonomorphicFlags( | 595 Code::Flags flags = Code::ComputeMonomorphicFlags( |
604 kind, extra_state, Code::CONSTANT_FUNCTION, argc, cache_holder); | 596 kind, extra_state, Code::CONSTANT_FUNCTION, argc, cache_holder); |
605 Handle<Object> probe(map_holder->map()->FindInCodeCache(*name, flags), | 597 Handle<Object> probe(stub_holder->map()->FindInCodeCache(*name, flags), |
606 isolate_); | 598 isolate_); |
607 if (probe->IsCode()) return Handle<Code>::cast(probe); | 599 if (probe->IsCode()) return Handle<Code>::cast(probe); |
608 | 600 |
609 CallStubCompiler compiler(isolate_, argc, kind, extra_state, cache_holder); | 601 CallStubCompiler compiler(isolate_, argc, kind, extra_state, cache_holder); |
610 Handle<Code> code = | 602 Handle<Code> code = |
611 compiler.CompileCallConstant(object, holder, name, check, function); | 603 compiler.CompileCallConstant(object, holder, name, check, function); |
612 code->set_check_type(check); | 604 code->set_check_type(check); |
613 ASSERT_EQ(flags, code->flags()); | 605 ASSERT_EQ(flags, code->flags()); |
614 PROFILE(isolate_, | 606 PROFILE(isolate_, |
615 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG), *code, *name)); | 607 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG), *code, *name)); |
616 GDBJIT(AddCode(GDBJITInterface::CALL_IC, *name, *code)); | 608 GDBJIT(AddCode(GDBJITInterface::CALL_IC, *name, *code)); |
617 JSObject::UpdateMapCodeCache(map_holder, name, code); | 609 JSObject::UpdateMapCodeCache(stub_holder, name, code); |
618 return code; | 610 return code; |
619 } | 611 } |
620 | 612 |
621 | 613 |
622 Handle<Code> StubCache::ComputeCallField(int argc, | 614 Handle<Code> StubCache::ComputeCallField(int argc, |
623 Code::Kind kind, | 615 Code::Kind kind, |
624 Code::ExtraICState extra_state, | 616 Code::ExtraICState extra_state, |
625 Handle<String> name, | 617 Handle<String> name, |
626 Handle<Object> object, | 618 Handle<Object> object, |
627 Handle<JSObject> holder, | 619 Handle<JSObject> holder, |
628 PropertyIndex index) { | 620 PropertyIndex index) { |
629 // Compute the check type and the map. | 621 // Compute the check type and the map. |
630 InlineCacheHolderFlag cache_holder = | 622 InlineCacheHolderFlag cache_holder = |
631 IC::GetCodeCacheForObject(*object, *holder); | 623 IC::GetCodeCacheForObject(*object, *holder); |
632 Handle<JSObject> map_holder( | 624 Handle<JSObject> stub_holder(IC::GetCodeCacheHolder( |
633 IC::GetCodeCacheHolder(isolate_, *object, cache_holder)); | 625 isolate_, *object, cache_holder)); |
634 | 626 |
635 // TODO(1233596): We cannot do receiver map check for non-JS objects | 627 // TODO(1233596): We cannot do receiver map check for non-JS objects |
636 // because they may be represented as immediates without a | 628 // because they may be represented as immediates without a |
637 // map. Instead, we check against the map in the holder. | 629 // map. Instead, we check against the map in the holder. |
638 if (object->IsNumber() || object->IsSymbol() || | 630 if (object->IsNumber() || object->IsSymbol() || |
639 object->IsBoolean() || object->IsString()) { | 631 object->IsBoolean() || object->IsString()) { |
640 object = holder; | 632 object = holder; |
641 } | 633 } |
642 | 634 |
643 Code::Flags flags = Code::ComputeMonomorphicFlags( | 635 Code::Flags flags = Code::ComputeMonomorphicFlags( |
644 kind, extra_state, Code::FIELD, argc, cache_holder); | 636 kind, extra_state, Code::FIELD, argc, cache_holder); |
645 Handle<Object> probe(map_holder->map()->FindInCodeCache(*name, flags), | 637 Handle<Object> probe(stub_holder->map()->FindInCodeCache(*name, flags), |
646 isolate_); | 638 isolate_); |
647 if (probe->IsCode()) return Handle<Code>::cast(probe); | 639 if (probe->IsCode()) return Handle<Code>::cast(probe); |
648 | 640 |
649 CallStubCompiler compiler(isolate_, argc, kind, extra_state, cache_holder); | 641 CallStubCompiler compiler(isolate_, argc, kind, extra_state, cache_holder); |
650 Handle<Code> code = | 642 Handle<Code> code = |
651 compiler.CompileCallField(Handle<JSObject>::cast(object), | 643 compiler.CompileCallField(Handle<JSObject>::cast(object), |
652 holder, index, name); | 644 holder, index, name); |
653 ASSERT_EQ(flags, code->flags()); | 645 ASSERT_EQ(flags, code->flags()); |
654 PROFILE(isolate_, | 646 PROFILE(isolate_, |
655 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG), *code, *name)); | 647 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG), *code, *name)); |
656 GDBJIT(AddCode(GDBJITInterface::CALL_IC, *name, *code)); | 648 GDBJIT(AddCode(GDBJITInterface::CALL_IC, *name, *code)); |
657 JSObject::UpdateMapCodeCache(map_holder, name, code); | 649 JSObject::UpdateMapCodeCache(stub_holder, name, code); |
658 return code; | 650 return code; |
659 } | 651 } |
660 | 652 |
661 | 653 |
662 Handle<Code> StubCache::ComputeCallInterceptor(int argc, | 654 Handle<Code> StubCache::ComputeCallInterceptor(int argc, |
663 Code::Kind kind, | 655 Code::Kind kind, |
664 Code::ExtraICState extra_state, | 656 Code::ExtraICState extra_state, |
665 Handle<String> name, | 657 Handle<String> name, |
666 Handle<Object> object, | 658 Handle<Object> object, |
667 Handle<JSObject> holder) { | 659 Handle<JSObject> holder) { |
668 // Compute the check type and the map. | 660 // Compute the check type and the map. |
669 InlineCacheHolderFlag cache_holder = | 661 InlineCacheHolderFlag cache_holder = |
670 IC::GetCodeCacheForObject(*object, *holder); | 662 IC::GetCodeCacheForObject(*object, *holder); |
671 Handle<JSObject> map_holder( | 663 Handle<JSObject> stub_holder(IC::GetCodeCacheHolder( |
672 IC::GetCodeCacheHolder(isolate_, *object, cache_holder)); | 664 isolate_, *object, cache_holder)); |
673 | 665 |
674 // TODO(1233596): We cannot do receiver map check for non-JS objects | 666 // TODO(1233596): We cannot do receiver map check for non-JS objects |
675 // because they may be represented as immediates without a | 667 // because they may be represented as immediates without a |
676 // map. Instead, we check against the map in the holder. | 668 // map. Instead, we check against the map in the holder. |
677 if (object->IsNumber() || object->IsSymbol() || | 669 if (object->IsNumber() || object->IsSymbol() || |
678 object->IsBoolean() || object->IsString()) { | 670 object->IsBoolean() || object->IsString()) { |
679 object = holder; | 671 object = holder; |
680 } | 672 } |
681 | 673 |
682 Code::Flags flags = Code::ComputeMonomorphicFlags( | 674 Code::Flags flags = Code::ComputeMonomorphicFlags( |
683 kind, extra_state, Code::INTERCEPTOR, argc, cache_holder); | 675 kind, extra_state, Code::INTERCEPTOR, argc, cache_holder); |
684 Handle<Object> probe(map_holder->map()->FindInCodeCache(*name, flags), | 676 Handle<Object> probe(stub_holder->map()->FindInCodeCache(*name, flags), |
685 isolate_); | 677 isolate_); |
686 if (probe->IsCode()) return Handle<Code>::cast(probe); | 678 if (probe->IsCode()) return Handle<Code>::cast(probe); |
687 | 679 |
688 CallStubCompiler compiler(isolate(), argc, kind, extra_state, cache_holder); | 680 CallStubCompiler compiler(isolate(), argc, kind, extra_state, cache_holder); |
689 Handle<Code> code = | 681 Handle<Code> code = |
690 compiler.CompileCallInterceptor(Handle<JSObject>::cast(object), | 682 compiler.CompileCallInterceptor(Handle<JSObject>::cast(object), |
691 holder, name); | 683 holder, name); |
692 ASSERT_EQ(flags, code->flags()); | 684 ASSERT_EQ(flags, code->flags()); |
693 PROFILE(isolate(), | 685 PROFILE(isolate(), |
694 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG), *code, *name)); | 686 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG), *code, *name)); |
695 GDBJIT(AddCode(GDBJITInterface::CALL_IC, *name, *code)); | 687 GDBJIT(AddCode(GDBJITInterface::CALL_IC, *name, *code)); |
696 JSObject::UpdateMapCodeCache(map_holder, name, code); | 688 JSObject::UpdateMapCodeCache(stub_holder, name, code); |
697 return code; | 689 return code; |
698 } | 690 } |
699 | 691 |
700 | 692 |
701 Handle<Code> StubCache::ComputeCallGlobal(int argc, | 693 Handle<Code> StubCache::ComputeCallGlobal(int argc, |
702 Code::Kind kind, | 694 Code::Kind kind, |
703 Code::ExtraICState extra_state, | 695 Code::ExtraICState extra_state, |
704 Handle<String> name, | 696 Handle<String> name, |
705 Handle<JSObject> receiver, | 697 Handle<JSObject> receiver, |
706 Handle<GlobalObject> holder, | 698 Handle<GlobalObject> holder, |
707 Handle<JSGlobalPropertyCell> cell, | 699 Handle<JSGlobalPropertyCell> cell, |
708 Handle<JSFunction> function) { | 700 Handle<JSFunction> function) { |
709 InlineCacheHolderFlag cache_holder = | 701 InlineCacheHolderFlag cache_holder = |
710 IC::GetCodeCacheForObject(*receiver, *holder); | 702 IC::GetCodeCacheForObject(*receiver, *holder); |
711 Handle<JSObject> map_holder(IC::GetCodeCacheHolder( | 703 Handle<JSObject> stub_holder(IC::GetCodeCacheHolder( |
712 isolate_, *receiver, cache_holder)); | 704 isolate_, *receiver, cache_holder)); |
713 Code::Flags flags = Code::ComputeMonomorphicFlags( | 705 Code::Flags flags = Code::ComputeMonomorphicFlags( |
714 kind, extra_state, Code::NORMAL, argc, cache_holder); | 706 kind, extra_state, Code::NORMAL, argc, cache_holder); |
715 Handle<Object> probe(map_holder->map()->FindInCodeCache(*name, flags), | 707 Handle<Object> probe(stub_holder->map()->FindInCodeCache(*name, flags), |
716 isolate_); | 708 isolate_); |
717 if (probe->IsCode()) return Handle<Code>::cast(probe); | 709 if (probe->IsCode()) return Handle<Code>::cast(probe); |
718 | 710 |
719 CallStubCompiler compiler(isolate(), argc, kind, extra_state, cache_holder); | 711 CallStubCompiler compiler(isolate(), argc, kind, extra_state, cache_holder); |
720 Handle<Code> code = | 712 Handle<Code> code = |
721 compiler.CompileCallGlobal(receiver, holder, cell, function, name); | 713 compiler.CompileCallGlobal(receiver, holder, cell, function, name); |
722 ASSERT_EQ(flags, code->flags()); | 714 ASSERT_EQ(flags, code->flags()); |
723 PROFILE(isolate(), | 715 PROFILE(isolate(), |
724 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG), *code, *name)); | 716 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG), *code, *name)); |
725 GDBJIT(AddCode(GDBJITInterface::CALL_IC, *name, *code)); | 717 GDBJIT(AddCode(GDBJITInterface::CALL_IC, *name, *code)); |
726 JSObject::UpdateMapCodeCache(map_holder, name, code); | 718 JSObject::UpdateMapCodeCache(stub_holder, name, code); |
727 return code; | 719 return code; |
728 } | 720 } |
729 | 721 |
730 | 722 |
731 static void FillCache(Isolate* isolate, Handle<Code> code) { | 723 static void FillCache(Isolate* isolate, Handle<Code> code) { |
732 Handle<UnseededNumberDictionary> dictionary = | 724 Handle<UnseededNumberDictionary> dictionary = |
733 UnseededNumberDictionary::Set(isolate->factory()->non_monomorphic_cache(), | 725 UnseededNumberDictionary::Set(isolate->factory()->non_monomorphic_cache(), |
734 code->flags(), | 726 code->flags(), |
735 code); | 727 code); |
736 isolate->heap()->public_set_non_monomorphic_cache(*dictionary); | 728 isolate->heap()->public_set_non_monomorphic_cache(*dictionary); |
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
878 | 870 |
879 | 871 |
880 Handle<Code> StubCache::ComputeLoadElementPolymorphic( | 872 Handle<Code> StubCache::ComputeLoadElementPolymorphic( |
881 MapHandleList* receiver_maps) { | 873 MapHandleList* receiver_maps) { |
882 Code::Flags flags = Code::ComputeFlags(Code::KEYED_LOAD_IC, POLYMORPHIC); | 874 Code::Flags flags = Code::ComputeFlags(Code::KEYED_LOAD_IC, POLYMORPHIC); |
883 Handle<PolymorphicCodeCache> cache = | 875 Handle<PolymorphicCodeCache> cache = |
884 isolate_->factory()->polymorphic_code_cache(); | 876 isolate_->factory()->polymorphic_code_cache(); |
885 Handle<Object> probe = cache->Lookup(receiver_maps, flags); | 877 Handle<Object> probe = cache->Lookup(receiver_maps, flags); |
886 if (probe->IsCode()) return Handle<Code>::cast(probe); | 878 if (probe->IsCode()) return Handle<Code>::cast(probe); |
887 | 879 |
| 880 CodeHandleList handlers(receiver_maps->length()); |
888 KeyedLoadStubCompiler compiler(isolate_); | 881 KeyedLoadStubCompiler compiler(isolate_); |
889 Handle<Code> code = compiler.CompileLoadElementPolymorphic(receiver_maps); | 882 compiler.CompileElementHandlers(receiver_maps, &handlers); |
| 883 Handle<Code> code = compiler.CompilePolymorphicIC( |
| 884 receiver_maps, &handlers, factory()->empty_string(), |
| 885 Code::NORMAL, ELEMENT); |
| 886 |
| 887 isolate()->counters()->keyed_load_polymorphic_stubs()->Increment(); |
| 888 |
890 PolymorphicCodeCache::Update(cache, receiver_maps, flags, code); | 889 PolymorphicCodeCache::Update(cache, receiver_maps, flags, code); |
891 return code; | 890 return code; |
892 } | 891 } |
893 | 892 |
894 | 893 |
| 894 Handle<Code> StubCache::ComputePolymorphicIC(MapHandleList* receiver_maps, |
| 895 CodeHandleList* handlers, |
| 896 Handle<String> name) { |
| 897 LoadStubCompiler ic_compiler(isolate_); |
| 898 Handle<Code> ic = ic_compiler.CompilePolymorphicIC( |
| 899 receiver_maps, handlers, name, Code::NORMAL, PROPERTY); |
| 900 return ic; |
| 901 } |
| 902 |
| 903 |
895 Handle<Code> StubCache::ComputeStoreElementPolymorphic( | 904 Handle<Code> StubCache::ComputeStoreElementPolymorphic( |
896 MapHandleList* receiver_maps, | 905 MapHandleList* receiver_maps, |
897 KeyedAccessGrowMode grow_mode, | 906 KeyedAccessGrowMode grow_mode, |
898 StrictModeFlag strict_mode) { | 907 StrictModeFlag strict_mode) { |
899 Handle<PolymorphicCodeCache> cache = | 908 Handle<PolymorphicCodeCache> cache = |
900 isolate_->factory()->polymorphic_code_cache(); | 909 isolate_->factory()->polymorphic_code_cache(); |
901 Code::ExtraICState extra_state = Code::ComputeExtraICState(grow_mode, | 910 Code::ExtraICState extra_state = Code::ComputeExtraICState(grow_mode, |
902 strict_mode); | 911 strict_mode); |
903 Code::Flags flags = | 912 Code::Flags flags = |
904 Code::ComputeFlags(Code::KEYED_STORE_IC, POLYMORPHIC, extra_state); | 913 Code::ComputeFlags(Code::KEYED_STORE_IC, POLYMORPHIC, extra_state); |
(...skipping 474 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1379 } | 1388 } |
1380 | 1389 |
1381 | 1390 |
1382 #define __ ACCESS_MASM(masm()) | 1391 #define __ ACCESS_MASM(masm()) |
1383 | 1392 |
1384 | 1393 |
1385 Register BaseLoadStubCompiler::HandlerFrontendHeader(Handle<JSObject> object, | 1394 Register BaseLoadStubCompiler::HandlerFrontendHeader(Handle<JSObject> object, |
1386 Register object_reg, | 1395 Register object_reg, |
1387 Handle<JSObject> holder, | 1396 Handle<JSObject> holder, |
1388 Handle<String> name, | 1397 Handle<String> name, |
1389 Label* miss, | 1398 Label* miss) { |
1390 FrontendCheckType check) { | |
1391 if (check == PERFORM_INITIAL_CHECKS) { | |
1392 GenerateNameCheck(name, this->name(), miss); | |
1393 // Check that the receiver isn't a smi. | |
1394 __ JumpIfSmi(object_reg, miss); | |
1395 } | |
1396 | |
1397 // Check the prototype chain. | 1399 // Check the prototype chain. |
1398 return CheckPrototypes(object, object_reg, holder, | 1400 return CheckPrototypes(object, object_reg, holder, |
1399 scratch1(), scratch2(), scratch3(), | 1401 scratch1(), scratch2(), scratch3(), |
1400 name, miss); | 1402 name, miss, SKIP_RECEIVER); |
1401 } | 1403 } |
1402 | 1404 |
1403 | 1405 |
1404 Register BaseLoadStubCompiler::HandlerFrontend(Handle<JSObject> object, | 1406 Register BaseLoadStubCompiler::HandlerFrontend(Handle<JSObject> object, |
1405 Register object_reg, | 1407 Register object_reg, |
1406 Handle<JSObject> holder, | 1408 Handle<JSObject> holder, |
1407 Handle<String> name, | 1409 Handle<String> name, |
1408 Label* success, | 1410 Label* success) { |
1409 FrontendCheckType check) { | |
1410 Label miss; | 1411 Label miss; |
1411 | 1412 |
1412 Register reg = HandlerFrontendHeader( | 1413 Register reg = HandlerFrontendHeader(object, object_reg, holder, name, &miss); |
1413 object, object_reg, holder, name, &miss, check); | |
1414 | 1414 |
1415 HandlerFrontendFooter(success, &miss); | 1415 HandlerFrontendFooter(success, &miss); |
1416 return reg; | 1416 return reg; |
1417 } | 1417 } |
1418 | 1418 |
1419 | 1419 |
1420 Handle<Code> BaseLoadStubCompiler::CompileLoadField(Handle<JSObject> object, | 1420 Handle<Code> BaseLoadStubCompiler::CompileLoadField(Handle<JSObject> object, |
1421 Handle<JSObject> holder, | 1421 Handle<JSObject> holder, |
1422 Handle<String> name, | 1422 Handle<String> name, |
1423 PropertyIndex index) { | 1423 PropertyIndex field) { |
1424 Label success; | 1424 Label miss; |
1425 Register reg = HandlerFrontend(object, receiver(), holder, name, | 1425 |
1426 &success, PERFORM_INITIAL_CHECKS); | 1426 Register reg = HandlerFrontendHeader(object, receiver(), holder, name, &miss); |
1427 __ bind(&success); | 1427 |
1428 GenerateLoadField(reg, holder, index); | 1428 LoadFieldStub stub(reg, field.is_inobject(holder), field.translate(holder)); |
| 1429 GenerateTailCall(stub.GetCode(isolate())); |
| 1430 |
| 1431 __ bind(&miss); |
| 1432 GenerateLoadMiss(masm(), kind()); |
1429 | 1433 |
1430 // Return the generated code. | 1434 // Return the generated code. |
1431 return GetCode(Code::FIELD, name); | 1435 return GetCode(Code::HANDLER_FRAGMENT, Code::FIELD, name); |
1432 } | 1436 } |
1433 | 1437 |
1434 | 1438 |
1435 Handle<Code> BaseLoadStubCompiler::CompileLoadConstant( | 1439 Handle<Code> BaseLoadStubCompiler::CompileLoadConstant( |
1436 Handle<JSObject> object, | 1440 Handle<JSObject> object, |
1437 Handle<JSObject> holder, | 1441 Handle<JSObject> holder, |
1438 Handle<String> name, | 1442 Handle<String> name, |
1439 Handle<JSFunction> value) { | 1443 Handle<JSFunction> value) { |
1440 Label success; | 1444 Label success; |
1441 HandlerFrontend(object, receiver(), holder, name, | 1445 HandlerFrontend(object, receiver(), holder, name, &success); |
1442 &success, PERFORM_INITIAL_CHECKS); | |
1443 __ bind(&success); | 1446 __ bind(&success); |
1444 GenerateLoadConstant(value); | 1447 GenerateLoadConstant(value); |
1445 | 1448 |
1446 // Return the generated code. | 1449 // Return the generated code. |
1447 return GetCode(Code::CONSTANT_FUNCTION, name); | 1450 return GetCode(Code::HANDLER_FRAGMENT, Code::CONSTANT_FUNCTION, name); |
1448 } | 1451 } |
1449 | 1452 |
1450 | 1453 |
1451 Handle<Code> BaseLoadStubCompiler::CompileLoadCallback( | 1454 Handle<Code> BaseLoadStubCompiler::CompileLoadCallback( |
1452 Handle<JSObject> object, | 1455 Handle<JSObject> object, |
1453 Handle<JSObject> holder, | 1456 Handle<JSObject> holder, |
1454 Handle<String> name, | 1457 Handle<String> name, |
1455 Handle<ExecutableAccessorInfo> callback) { | 1458 Handle<ExecutableAccessorInfo> callback) { |
1456 Label success; | 1459 Label success; |
1457 | 1460 |
1458 Register reg = CallbackHandlerFrontend( | 1461 Register reg = CallbackHandlerFrontend( |
1459 object, receiver(), holder, name, &success, | 1462 object, receiver(), holder, name, &success, callback); |
1460 PERFORM_INITIAL_CHECKS, callback); | |
1461 __ bind(&success); | 1463 __ bind(&success); |
1462 GenerateLoadCallback(reg, callback); | 1464 GenerateLoadCallback(reg, callback); |
1463 | 1465 |
1464 // Return the generated code. | 1466 // Return the generated code. |
1465 return GetCode(Code::CALLBACKS, name); | 1467 return GetCode(Code::HANDLER_FRAGMENT, Code::CALLBACKS, name); |
1466 } | 1468 } |
1467 | 1469 |
1468 | 1470 |
1469 Handle<Code> BaseLoadStubCompiler::CompileLoadInterceptor( | 1471 Handle<Code> BaseLoadStubCompiler::CompileLoadInterceptor( |
1470 Handle<JSObject> object, | 1472 Handle<JSObject> object, |
1471 Handle<JSObject> holder, | 1473 Handle<JSObject> holder, |
1472 Handle<String> name) { | 1474 Handle<String> name) { |
1473 Label success; | 1475 Label success; |
1474 | 1476 |
1475 LookupResult lookup(isolate()); | 1477 LookupResult lookup(isolate()); |
1476 LookupPostInterceptor(holder, name, &lookup); | 1478 LookupPostInterceptor(holder, name, &lookup); |
1477 | 1479 |
1478 Register reg = HandlerFrontend(object, receiver(), holder, name, | 1480 Register reg = HandlerFrontend(object, receiver(), holder, name, &success); |
1479 &success, PERFORM_INITIAL_CHECKS); | |
1480 __ bind(&success); | 1481 __ bind(&success); |
1481 // TODO(368): Compile in the whole chain: all the interceptors in | 1482 // TODO(368): Compile in the whole chain: all the interceptors in |
1482 // prototypes and ultimate answer. | 1483 // prototypes and ultimate answer. |
1483 GenerateLoadInterceptor(reg, object, holder, &lookup, name); | 1484 GenerateLoadInterceptor(reg, object, holder, &lookup, name); |
1484 | 1485 |
1485 // Return the generated code. | 1486 // Return the generated code. |
1486 return GetCode(Code::INTERCEPTOR, name); | 1487 return GetCode(Code::HANDLER_FRAGMENT, Code::INTERCEPTOR, name); |
1487 } | 1488 } |
1488 | 1489 |
1489 | 1490 |
1490 void BaseLoadStubCompiler::GenerateLoadPostInterceptor( | 1491 void BaseLoadStubCompiler::GenerateLoadPostInterceptor( |
1491 Register interceptor_reg, | 1492 Register interceptor_reg, |
1492 Handle<JSObject> interceptor_holder, | 1493 Handle<JSObject> interceptor_holder, |
1493 Handle<String> name, | 1494 Handle<String> name, |
1494 LookupResult* lookup) { | 1495 LookupResult* lookup) { |
1495 Label success; | 1496 Label success; |
1496 Handle<JSObject> holder(lookup->holder()); | 1497 Handle<JSObject> holder(lookup->holder()); |
1497 if (lookup->IsField()) { | 1498 if (lookup->IsField()) { |
1498 // We found FIELD property in prototype chain of interceptor's holder. | 1499 PropertyIndex field = lookup->GetFieldIndex(); |
1499 // Retrieve a field from field's holder. | 1500 if (interceptor_holder.is_identical_to(holder)) { |
1500 Register reg = HandlerFrontend(interceptor_holder, interceptor_reg, holder, | 1501 LoadFieldStub stub(interceptor_reg, |
1501 name, &success, SKIP_INITIAL_CHECKS); | 1502 field.is_inobject(holder), |
1502 __ bind(&success); | 1503 field.translate(holder)); |
1503 GenerateLoadField(reg, holder, lookup->GetFieldIndex()); | 1504 GenerateTailCall(stub.GetCode(isolate())); |
| 1505 } else { |
| 1506 // We found FIELD property in prototype chain of interceptor's holder. |
| 1507 // Retrieve a field from field's holder. |
| 1508 Register reg = HandlerFrontend( |
| 1509 interceptor_holder, interceptor_reg, holder, name, &success); |
| 1510 __ bind(&success); |
| 1511 GenerateLoadField(reg, holder, field); |
| 1512 } |
1504 } else { | 1513 } else { |
1505 // We found CALLBACKS property in prototype chain of interceptor's | 1514 // We found CALLBACKS property in prototype chain of interceptor's |
1506 // holder. | 1515 // holder. |
1507 ASSERT(lookup->type() == CALLBACKS); | 1516 ASSERT(lookup->type() == CALLBACKS); |
1508 Handle<ExecutableAccessorInfo> callback( | 1517 Handle<ExecutableAccessorInfo> callback( |
1509 ExecutableAccessorInfo::cast(lookup->GetCallbackObject())); | 1518 ExecutableAccessorInfo::cast(lookup->GetCallbackObject())); |
1510 ASSERT(callback->getter() != NULL); | 1519 ASSERT(callback->getter() != NULL); |
1511 | 1520 |
1512 Register reg = CallbackHandlerFrontend( | 1521 Register reg = CallbackHandlerFrontend( |
1513 interceptor_holder, interceptor_reg, holder, | 1522 interceptor_holder, interceptor_reg, holder, name, &success, callback); |
1514 name, &success, SKIP_INITIAL_CHECKS, callback); | |
1515 __ bind(&success); | 1523 __ bind(&success); |
1516 GenerateLoadCallback(reg, callback); | 1524 GenerateLoadCallback(reg, callback); |
1517 } | 1525 } |
1518 } | 1526 } |
1519 | 1527 |
1520 | 1528 |
| 1529 Handle<Code> BaseLoadStubCompiler::CompileMonomorphicIC( |
| 1530 Handle<Map> receiver_map, |
| 1531 Handle<Code> handler, |
| 1532 Handle<String> name) { |
| 1533 MapHandleList receiver_maps(1); |
| 1534 receiver_maps.Add(receiver_map); |
| 1535 CodeHandleList handlers(1); |
| 1536 handlers.Add(handler); |
| 1537 Code::StubType type = handler->type(); |
| 1538 return CompilePolymorphicIC(&receiver_maps, &handlers, name, type, PROPERTY); |
| 1539 } |
| 1540 |
| 1541 |
1521 Handle<Code> LoadStubCompiler::CompileLoadViaGetter( | 1542 Handle<Code> LoadStubCompiler::CompileLoadViaGetter( |
1522 Handle<JSObject> object, | 1543 Handle<JSObject> object, |
1523 Handle<JSObject> holder, | 1544 Handle<JSObject> holder, |
1524 Handle<String> name, | 1545 Handle<String> name, |
1525 Handle<JSFunction> getter) { | 1546 Handle<JSFunction> getter) { |
1526 Label success; | 1547 Label success; |
1527 HandlerFrontend(object, receiver(), holder, name, | 1548 HandlerFrontend(object, receiver(), holder, name, &success); |
1528 &success, PERFORM_INITIAL_CHECKS); | |
1529 | 1549 |
1530 __ bind(&success); | 1550 __ bind(&success); |
1531 GenerateLoadViaGetter(masm(), getter); | 1551 GenerateLoadViaGetter(masm(), getter); |
1532 | 1552 |
1533 // Return the generated code. | 1553 // Return the generated code. |
1534 return GetCode(Code::CALLBACKS, name); | 1554 return GetCode(Code::HANDLER_FRAGMENT, Code::CALLBACKS, name); |
1535 } | 1555 } |
1536 | 1556 |
1537 | 1557 |
1538 #undef __ | 1558 #undef __ |
1539 | 1559 |
1540 | 1560 |
1541 Handle<Code> LoadStubCompiler::GetCode(Code::StubType type, | 1561 void LoadStubCompiler::JitEvent(Handle<String> name, Handle<Code> code) { |
1542 Handle<String> name, | 1562 GDBJIT(AddCode(GDBJITInterface::LOAD_IC, *name, *code)); |
1543 InlineCacheState state) { | 1563 } |
1544 Code::Flags flags = Code::ComputeMonomorphicFlags( | 1564 |
1545 Code::LOAD_IC, Code::kNoExtraICState, type); | 1565 |
| 1566 void KeyedLoadStubCompiler::JitEvent(Handle<String> name, Handle<Code> code) { |
| 1567 GDBJIT(AddCode(GDBJITInterface::KEYED_LOAD_IC, *name, *code)); |
| 1568 } |
| 1569 |
| 1570 |
| 1571 Handle<Code> BaseLoadStubCompiler::GetCode(Code::IcFragment fragment, |
| 1572 Code::StubType type, |
| 1573 Handle<String> name, |
| 1574 InlineCacheState state) { |
| 1575 Code::Flags flags = Code::ComputeFlags(kind(), state, fragment, type); |
1546 Handle<Code> code = GetCodeWithFlags(flags, name); | 1576 Handle<Code> code = GetCodeWithFlags(flags, name); |
1547 PROFILE(isolate(), CodeCreateEvent(Logger::LOAD_IC_TAG, *code, *name)); | 1577 PROFILE(isolate(), CodeCreateEvent(log_kind(code), *code, *name)); |
1548 GDBJIT(AddCode(GDBJITInterface::LOAD_IC, *name, *code)); | 1578 JitEvent(name, code); |
1549 return code; | 1579 return code; |
1550 } | 1580 } |
1551 | 1581 |
1552 | 1582 |
1553 Handle<Code> KeyedLoadStubCompiler::GetCode(Code::StubType type, | 1583 void KeyedLoadStubCompiler::CompileElementHandlers(MapHandleList* receiver_maps, |
1554 Handle<String> name, | 1584 CodeHandleList* handlers) { |
1555 InlineCacheState state) { | |
1556 Code::Flags flags = Code::ComputeFlags( | |
1557 Code::KEYED_LOAD_IC, state, Code::kNoExtraICState, type); | |
1558 Handle<Code> code = GetCodeWithFlags(flags, name); | |
1559 PROFILE(isolate(), CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, *code, *name)); | |
1560 GDBJIT(AddCode(GDBJITInterface::LOAD_IC, *name, *code)); | |
1561 return code; | |
1562 } | |
1563 | |
1564 | |
1565 Handle<Code> KeyedLoadStubCompiler::CompileLoadElementPolymorphic( | |
1566 MapHandleList* receiver_maps) { | |
1567 CodeHandleList handler_ics(receiver_maps->length()); | |
1568 for (int i = 0; i < receiver_maps->length(); ++i) { | 1585 for (int i = 0; i < receiver_maps->length(); ++i) { |
1569 Handle<Map> receiver_map = receiver_maps->at(i); | 1586 Handle<Map> receiver_map = receiver_maps->at(i); |
1570 Handle<Code> cached_stub; | 1587 Handle<Code> cached_stub; |
1571 | 1588 |
1572 if ((receiver_map->instance_type() & kNotStringTag) == 0) { | 1589 if ((receiver_map->instance_type() & kNotStringTag) == 0) { |
1573 cached_stub = isolate()->builtins()->KeyedLoadIC_String(); | 1590 cached_stub = isolate()->builtins()->KeyedLoadIC_String(); |
1574 } else { | 1591 } else { |
1575 bool is_js_array = receiver_map->instance_type() == JS_ARRAY_TYPE; | 1592 bool is_js_array = receiver_map->instance_type() == JS_ARRAY_TYPE; |
1576 ElementsKind elements_kind = receiver_map->elements_kind(); | 1593 ElementsKind elements_kind = receiver_map->elements_kind(); |
1577 | 1594 |
1578 if (IsFastElementsKind(elements_kind) || | 1595 if (IsFastElementsKind(elements_kind) || |
1579 IsExternalArrayElementsKind(elements_kind)) { | 1596 IsExternalArrayElementsKind(elements_kind)) { |
1580 cached_stub = | 1597 cached_stub = |
1581 KeyedLoadFastElementStub(is_js_array, | 1598 KeyedLoadFastElementStub(is_js_array, |
1582 elements_kind).GetCode(isolate()); | 1599 elements_kind).GetCode(isolate()); |
1583 } else { | 1600 } else { |
1584 ASSERT(elements_kind == DICTIONARY_ELEMENTS); | 1601 ASSERT(elements_kind == DICTIONARY_ELEMENTS); |
1585 cached_stub = KeyedLoadDictionaryElementStub().GetCode(isolate()); | 1602 cached_stub = KeyedLoadDictionaryElementStub().GetCode(isolate()); |
1586 } | 1603 } |
1587 } | 1604 } |
1588 | 1605 |
1589 handler_ics.Add(cached_stub); | 1606 handlers->Add(cached_stub); |
1590 } | 1607 } |
1591 Handle<Code> code = CompileLoadPolymorphic(receiver_maps, &handler_ics); | |
1592 isolate()->counters()->keyed_load_polymorphic_stubs()->Increment(); | |
1593 PROFILE(isolate(), | |
1594 CodeCreateEvent(Logger::KEYED_LOAD_POLYMORPHIC_IC_TAG, *code, 0)); | |
1595 return code; | |
1596 } | 1608 } |
1597 | 1609 |
1598 | 1610 |
1599 | |
1600 Handle<Code> StoreStubCompiler::GetCode(Code::StubType type, | 1611 Handle<Code> StoreStubCompiler::GetCode(Code::StubType type, |
1601 Handle<String> name) { | 1612 Handle<String> name) { |
1602 Code::Flags flags = Code::ComputeMonomorphicFlags( | 1613 Code::Flags flags = Code::ComputeMonomorphicFlags( |
1603 Code::STORE_IC, strict_mode_, type); | 1614 Code::STORE_IC, strict_mode_, type); |
1604 Handle<Code> code = GetCodeWithFlags(flags, name); | 1615 Handle<Code> code = GetCodeWithFlags(flags, name); |
1605 PROFILE(isolate(), CodeCreateEvent(Logger::STORE_IC_TAG, *code, *name)); | 1616 PROFILE(isolate(), CodeCreateEvent(Logger::STORE_IC_TAG, *code, *name)); |
1606 GDBJIT(AddCode(GDBJITInterface::STORE_IC, *name, *code)); | 1617 GDBJIT(AddCode(GDBJITInterface::STORE_IC, *name, *code)); |
1607 return code; | 1618 return code; |
1608 } | 1619 } |
1609 | 1620 |
1610 | 1621 |
1611 Handle<Code> KeyedStoreStubCompiler::GetCode(Code::StubType type, | 1622 Handle<Code> KeyedStoreStubCompiler::GetCode(Code::StubType type, |
1612 Handle<String> name, | 1623 Handle<String> name, |
1613 InlineCacheState state) { | 1624 InlineCacheState state) { |
1614 Code::ExtraICState extra_state = | 1625 Code::ExtraICState extra_state = |
1615 Code::ComputeExtraICState(grow_mode_, strict_mode_); | 1626 Code::ComputeExtraICState(grow_mode_, strict_mode_); |
1616 Code::Flags flags = | 1627 Code::Flags flags = |
1617 Code::ComputeFlags(Code::KEYED_STORE_IC, state, extra_state, type); | 1628 Code::ComputeFlags(Code::KEYED_STORE_IC, state, extra_state, type); |
1618 Handle<Code> code = GetCodeWithFlags(flags, name); | 1629 Handle<Code> code = GetCodeWithFlags(flags, name); |
1619 PROFILE(isolate(), CodeCreateEvent(Logger::KEYED_STORE_IC_TAG, *code, *name)); | 1630 PROFILE(isolate(), CodeCreateEvent(Logger::KEYED_STORE_IC_TAG, *code, *name)); |
1620 GDBJIT(AddCode(GDBJITInterface::KEYED_STORE_IC, *name, *code)); | 1631 GDBJIT(AddCode(GDBJITInterface::KEYED_STORE_IC, *name, *code)); |
1621 return code; | 1632 return code; |
1622 } | 1633 } |
1623 | 1634 |
1624 | 1635 |
1625 Handle<Code> KeyedStoreStubCompiler::CompileStoreElementPolymorphic( | 1636 Handle<Code> KeyedStoreStubCompiler::CompileStoreElementPolymorphic( |
1626 MapHandleList* receiver_maps) { | 1637 MapHandleList* receiver_maps) { |
1627 // Collect MONOMORPHIC stubs for all |receiver_maps|. | 1638 // Collect MONOMORPHIC stubs for all |receiver_maps|. |
1628 CodeHandleList handler_ics(receiver_maps->length()); | 1639 CodeHandleList handlers(receiver_maps->length()); |
1629 MapHandleList transitioned_maps(receiver_maps->length()); | 1640 MapHandleList transitioned_maps(receiver_maps->length()); |
1630 for (int i = 0; i < receiver_maps->length(); ++i) { | 1641 for (int i = 0; i < receiver_maps->length(); ++i) { |
1631 Handle<Map> receiver_map(receiver_maps->at(i)); | 1642 Handle<Map> receiver_map(receiver_maps->at(i)); |
1632 Handle<Code> cached_stub; | 1643 Handle<Code> cached_stub; |
1633 Handle<Map> transitioned_map = | 1644 Handle<Map> transitioned_map = |
1634 receiver_map->FindTransitionedMap(receiver_maps); | 1645 receiver_map->FindTransitionedMap(receiver_maps); |
1635 | 1646 |
1636 // TODO(mvstanton): The code below is doing pessimistic elements | 1647 // TODO(mvstanton): The code below is doing pessimistic elements |
1637 // transitions. I would like to stop doing that and rely on Allocation Site | 1648 // transitions. I would like to stop doing that and rely on Allocation Site |
1638 // Tracking to do a better job of ensuring the data types are what they need | 1649 // Tracking to do a better job of ensuring the data types are what they need |
1639 // to be. Not all the elements are in place yet, pessimistic elements | 1650 // to be. Not all the elements are in place yet, pessimistic elements |
1640 // transitions are still important for performance. | 1651 // transitions are still important for performance. |
1641 bool is_js_array = receiver_map->instance_type() == JS_ARRAY_TYPE; | 1652 bool is_js_array = receiver_map->instance_type() == JS_ARRAY_TYPE; |
1642 ElementsKind elements_kind = receiver_map->elements_kind(); | 1653 ElementsKind elements_kind = receiver_map->elements_kind(); |
1643 if (!transitioned_map.is_null()) { | 1654 if (!transitioned_map.is_null()) { |
1644 cached_stub = ElementsTransitionAndStoreStub( | 1655 cached_stub = ElementsTransitionAndStoreStub( |
1645 elements_kind, | 1656 elements_kind, |
1646 transitioned_map->elements_kind(), | 1657 transitioned_map->elements_kind(), |
1647 is_js_array, | 1658 is_js_array, |
1648 strict_mode_, | 1659 strict_mode_, |
1649 grow_mode_).GetCode(isolate()); | 1660 grow_mode_).GetCode(isolate()); |
1650 } else { | 1661 } else { |
1651 cached_stub = KeyedStoreElementStub( | 1662 cached_stub = KeyedStoreElementStub( |
1652 is_js_array, | 1663 is_js_array, |
1653 elements_kind, | 1664 elements_kind, |
1654 grow_mode_).GetCode(isolate()); | 1665 grow_mode_).GetCode(isolate()); |
1655 } | 1666 } |
1656 ASSERT(!cached_stub.is_null()); | 1667 ASSERT(!cached_stub.is_null()); |
1657 handler_ics.Add(cached_stub); | 1668 handlers.Add(cached_stub); |
1658 transitioned_maps.Add(transitioned_map); | 1669 transitioned_maps.Add(transitioned_map); |
1659 } | 1670 } |
1660 Handle<Code> code = | 1671 Handle<Code> code = |
1661 CompileStorePolymorphic(receiver_maps, &handler_ics, &transitioned_maps); | 1672 CompileStorePolymorphic(receiver_maps, &handlers, &transitioned_maps); |
1662 isolate()->counters()->keyed_store_polymorphic_stubs()->Increment(); | 1673 isolate()->counters()->keyed_store_polymorphic_stubs()->Increment(); |
1663 PROFILE(isolate(), | 1674 PROFILE(isolate(), |
1664 CodeCreateEvent(Logger::KEYED_STORE_POLYMORPHIC_IC_TAG, *code, 0)); | 1675 CodeCreateEvent(Logger::KEYED_STORE_POLYMORPHIC_IC_TAG, *code, 0)); |
1665 return code; | 1676 return code; |
1666 } | 1677 } |
1667 | 1678 |
1668 | 1679 |
1669 void KeyedStoreStubCompiler::GenerateStoreDictionaryElement( | 1680 void KeyedStoreStubCompiler::GenerateStoreDictionaryElement( |
1670 MacroAssembler* masm) { | 1681 MacroAssembler* masm) { |
1671 KeyedStoreIC::GenerateSlow(masm); | 1682 KeyedStoreIC::GenerateSlow(masm); |
(...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1826 Handle<FunctionTemplateInfo>( | 1837 Handle<FunctionTemplateInfo>( |
1827 FunctionTemplateInfo::cast(signature->receiver())); | 1838 FunctionTemplateInfo::cast(signature->receiver())); |
1828 } | 1839 } |
1829 } | 1840 } |
1830 | 1841 |
1831 is_simple_api_call_ = true; | 1842 is_simple_api_call_ = true; |
1832 } | 1843 } |
1833 | 1844 |
1834 | 1845 |
1835 } } // namespace v8::internal | 1846 } } // namespace v8::internal |
OLD | NEW |