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