OLD | NEW |
1 // Copyright 2006-2009 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2009 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 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
87 } | 87 } |
88 | 88 |
89 // Update primary cache. | 89 // Update primary cache. |
90 primary->key = name; | 90 primary->key = name; |
91 primary->value = code; | 91 primary->value = code; |
92 return code; | 92 return code; |
93 } | 93 } |
94 | 94 |
95 | 95 |
96 Object* StubCache::ComputeLoadNonexistent(String* name, JSObject* receiver) { | 96 Object* StubCache::ComputeLoadNonexistent(String* name, JSObject* receiver) { |
| 97 ASSERT(receiver->IsGlobalObject() || receiver->HasFastProperties()); |
97 // If no global objects are present in the prototype chain, the load | 98 // If no global objects are present in the prototype chain, the load |
98 // nonexistent IC stub can be shared for all names for a given map | 99 // nonexistent IC stub can be shared for all names for a given map |
99 // and we use the empty string for the map cache in that case. If | 100 // and we use the empty string for the map cache in that case. If |
100 // there are global objects involved, we need to check global | 101 // there are global objects involved, we need to check global |
101 // property cells in the stub and therefore the stub will be | 102 // property cells in the stub and therefore the stub will be |
102 // specific to the name. | 103 // specific to the name. |
103 String* cache_name = Heap::empty_string(); | 104 String* cache_name = Heap::empty_string(); |
104 if (receiver->IsGlobalObject()) cache_name = name; | 105 if (receiver->IsGlobalObject()) cache_name = name; |
105 JSObject* last = receiver; | 106 JSObject* last = receiver; |
106 while (last->GetPrototype() != Heap::null_value()) { | 107 while (last->GetPrototype() != Heap::null_value()) { |
(...skipping 15 matching lines...) Expand all Loading... |
122 if (result->IsFailure()) return result; | 123 if (result->IsFailure()) return result; |
123 } | 124 } |
124 return code; | 125 return code; |
125 } | 126 } |
126 | 127 |
127 | 128 |
128 Object* StubCache::ComputeLoadField(String* name, | 129 Object* StubCache::ComputeLoadField(String* name, |
129 JSObject* receiver, | 130 JSObject* receiver, |
130 JSObject* holder, | 131 JSObject* holder, |
131 int field_index) { | 132 int field_index) { |
| 133 ASSERT(IC::GetCodeCacheForObject(receiver, holder) == OWN_MAP); |
| 134 Map* map = receiver->map(); |
132 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::LOAD_IC, FIELD); | 135 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::LOAD_IC, FIELD); |
133 Object* code = receiver->map()->FindInCodeCache(name, flags); | 136 Object* code = map->FindInCodeCache(name, flags); |
134 if (code->IsUndefined()) { | 137 if (code->IsUndefined()) { |
135 LoadStubCompiler compiler; | 138 LoadStubCompiler compiler; |
136 code = compiler.CompileLoadField(receiver, holder, field_index, name); | 139 code = compiler.CompileLoadField(receiver, holder, field_index, name); |
137 if (code->IsFailure()) return code; | 140 if (code->IsFailure()) return code; |
138 PROFILE(CodeCreateEvent(Logger::LOAD_IC_TAG, Code::cast(code), name)); | 141 PROFILE(CodeCreateEvent(Logger::LOAD_IC_TAG, Code::cast(code), name)); |
139 Object* result = receiver->map()->UpdateCodeCache(name, Code::cast(code)); | 142 Object* result = map->UpdateCodeCache(name, Code::cast(code)); |
140 if (result->IsFailure()) return result; | 143 if (result->IsFailure()) return result; |
141 } | 144 } |
142 return code; | 145 return code; |
143 } | 146 } |
144 | 147 |
145 | 148 |
146 Object* StubCache::ComputeLoadCallback(String* name, | 149 Object* StubCache::ComputeLoadCallback(String* name, |
147 JSObject* receiver, | 150 JSObject* receiver, |
148 JSObject* holder, | 151 JSObject* holder, |
149 AccessorInfo* callback) { | 152 AccessorInfo* callback) { |
150 ASSERT(v8::ToCData<Address>(callback->getter()) != 0); | 153 ASSERT(v8::ToCData<Address>(callback->getter()) != 0); |
| 154 ASSERT(IC::GetCodeCacheForObject(receiver, holder) == OWN_MAP); |
| 155 Map* map = receiver->map(); |
151 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::LOAD_IC, CALLBACKS); | 156 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::LOAD_IC, CALLBACKS); |
152 Object* code = receiver->map()->FindInCodeCache(name, flags); | 157 Object* code = map->FindInCodeCache(name, flags); |
153 if (code->IsUndefined()) { | 158 if (code->IsUndefined()) { |
154 LoadStubCompiler compiler; | 159 LoadStubCompiler compiler; |
155 code = compiler.CompileLoadCallback(name, receiver, holder, callback); | 160 code = compiler.CompileLoadCallback(name, receiver, holder, callback); |
156 if (code->IsFailure()) return code; | 161 if (code->IsFailure()) return code; |
157 PROFILE(CodeCreateEvent(Logger::LOAD_IC_TAG, Code::cast(code), name)); | 162 PROFILE(CodeCreateEvent(Logger::LOAD_IC_TAG, Code::cast(code), name)); |
158 Object* result = receiver->map()->UpdateCodeCache(name, Code::cast(code)); | 163 Object* result = map->UpdateCodeCache(name, Code::cast(code)); |
159 if (result->IsFailure()) return result; | 164 if (result->IsFailure()) return result; |
160 } | 165 } |
161 return code; | 166 return code; |
162 } | 167 } |
163 | 168 |
164 | 169 |
165 Object* StubCache::ComputeLoadConstant(String* name, | 170 Object* StubCache::ComputeLoadConstant(String* name, |
166 JSObject* receiver, | 171 JSObject* receiver, |
167 JSObject* holder, | 172 JSObject* holder, |
168 Object* value) { | 173 Object* value) { |
| 174 ASSERT(IC::GetCodeCacheForObject(receiver, holder) == OWN_MAP); |
| 175 Map* map = receiver->map(); |
169 Code::Flags flags = | 176 Code::Flags flags = |
170 Code::ComputeMonomorphicFlags(Code::LOAD_IC, CONSTANT_FUNCTION); | 177 Code::ComputeMonomorphicFlags(Code::LOAD_IC, CONSTANT_FUNCTION); |
171 Object* code = receiver->map()->FindInCodeCache(name, flags); | 178 Object* code = map->FindInCodeCache(name, flags); |
172 if (code->IsUndefined()) { | 179 if (code->IsUndefined()) { |
173 LoadStubCompiler compiler; | 180 LoadStubCompiler compiler; |
174 code = compiler.CompileLoadConstant(receiver, holder, value, name); | 181 code = compiler.CompileLoadConstant(receiver, holder, value, name); |
175 if (code->IsFailure()) return code; | 182 if (code->IsFailure()) return code; |
176 PROFILE(CodeCreateEvent(Logger::LOAD_IC_TAG, Code::cast(code), name)); | 183 PROFILE(CodeCreateEvent(Logger::LOAD_IC_TAG, Code::cast(code), name)); |
177 Object* result = receiver->map()->UpdateCodeCache(name, Code::cast(code)); | 184 Object* result = map->UpdateCodeCache(name, Code::cast(code)); |
178 if (result->IsFailure()) return result; | 185 if (result->IsFailure()) return result; |
179 } | 186 } |
180 return code; | 187 return code; |
181 } | 188 } |
182 | 189 |
183 | 190 |
184 Object* StubCache::ComputeLoadInterceptor(String* name, | 191 Object* StubCache::ComputeLoadInterceptor(String* name, |
185 JSObject* receiver, | 192 JSObject* receiver, |
186 JSObject* holder) { | 193 JSObject* holder) { |
| 194 ASSERT(IC::GetCodeCacheForObject(receiver, holder) == OWN_MAP); |
| 195 Map* map = receiver->map(); |
187 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::LOAD_IC, INTERCEPTOR); | 196 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::LOAD_IC, INTERCEPTOR); |
188 Object* code = receiver->map()->FindInCodeCache(name, flags); | 197 Object* code = map->FindInCodeCache(name, flags); |
189 if (code->IsUndefined()) { | 198 if (code->IsUndefined()) { |
190 LoadStubCompiler compiler; | 199 LoadStubCompiler compiler; |
191 code = compiler.CompileLoadInterceptor(receiver, holder, name); | 200 code = compiler.CompileLoadInterceptor(receiver, holder, name); |
192 if (code->IsFailure()) return code; | 201 if (code->IsFailure()) return code; |
193 PROFILE(CodeCreateEvent(Logger::LOAD_IC_TAG, Code::cast(code), name)); | 202 PROFILE(CodeCreateEvent(Logger::LOAD_IC_TAG, Code::cast(code), name)); |
194 Object* result = receiver->map()->UpdateCodeCache(name, Code::cast(code)); | 203 Object* result = map->UpdateCodeCache(name, Code::cast(code)); |
195 if (result->IsFailure()) return result; | 204 if (result->IsFailure()) return result; |
196 } | 205 } |
197 return code; | 206 return code; |
198 } | 207 } |
199 | 208 |
200 | 209 |
201 Object* StubCache::ComputeLoadNormal() { | 210 Object* StubCache::ComputeLoadNormal() { |
202 return Builtins::builtin(Builtins::LoadIC_Normal); | 211 return Builtins::builtin(Builtins::LoadIC_Normal); |
203 } | 212 } |
204 | 213 |
205 | 214 |
206 Object* StubCache::ComputeLoadGlobal(String* name, | 215 Object* StubCache::ComputeLoadGlobal(String* name, |
207 JSObject* receiver, | 216 JSObject* receiver, |
208 GlobalObject* holder, | 217 GlobalObject* holder, |
209 JSGlobalPropertyCell* cell, | 218 JSGlobalPropertyCell* cell, |
210 bool is_dont_delete) { | 219 bool is_dont_delete) { |
| 220 ASSERT(IC::GetCodeCacheForObject(receiver, holder) == OWN_MAP); |
| 221 Map* map = receiver->map(); |
211 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::LOAD_IC, NORMAL); | 222 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::LOAD_IC, NORMAL); |
212 Object* code = receiver->map()->FindInCodeCache(name, flags); | 223 Object* code = map->FindInCodeCache(name, flags); |
213 if (code->IsUndefined()) { | 224 if (code->IsUndefined()) { |
214 LoadStubCompiler compiler; | 225 LoadStubCompiler compiler; |
215 code = compiler.CompileLoadGlobal(receiver, | 226 code = compiler.CompileLoadGlobal(receiver, |
216 holder, | 227 holder, |
217 cell, | 228 cell, |
218 name, | 229 name, |
219 is_dont_delete); | 230 is_dont_delete); |
220 if (code->IsFailure()) return code; | 231 if (code->IsFailure()) return code; |
221 PROFILE(CodeCreateEvent(Logger::LOAD_IC_TAG, Code::cast(code), name)); | 232 PROFILE(CodeCreateEvent(Logger::LOAD_IC_TAG, Code::cast(code), name)); |
222 Object* result = receiver->map()->UpdateCodeCache(name, Code::cast(code)); | 233 Object* result = map->UpdateCodeCache(name, Code::cast(code)); |
223 if (result->IsFailure()) return result; | 234 if (result->IsFailure()) return result; |
224 } | 235 } |
225 return code; | 236 return code; |
226 } | 237 } |
227 | 238 |
228 | 239 |
229 Object* StubCache::ComputeKeyedLoadField(String* name, | 240 Object* StubCache::ComputeKeyedLoadField(String* name, |
230 JSObject* receiver, | 241 JSObject* receiver, |
231 JSObject* holder, | 242 JSObject* holder, |
232 int field_index) { | 243 int field_index) { |
| 244 ASSERT(IC::GetCodeCacheForObject(receiver, holder) == OWN_MAP); |
| 245 Map* map = receiver->map(); |
233 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, FIELD); | 246 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, FIELD); |
234 Object* code = receiver->map()->FindInCodeCache(name, flags); | 247 Object* code = map->FindInCodeCache(name, flags); |
235 if (code->IsUndefined()) { | 248 if (code->IsUndefined()) { |
236 KeyedLoadStubCompiler compiler; | 249 KeyedLoadStubCompiler compiler; |
237 code = compiler.CompileLoadField(name, receiver, holder, field_index); | 250 code = compiler.CompileLoadField(name, receiver, holder, field_index); |
238 if (code->IsFailure()) return code; | 251 if (code->IsFailure()) return code; |
239 PROFILE(CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, Code::cast(code), name)); | 252 PROFILE(CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, Code::cast(code), name)); |
240 Object* result = receiver->map()->UpdateCodeCache(name, Code::cast(code)); | 253 Object* result = map->UpdateCodeCache(name, Code::cast(code)); |
241 if (result->IsFailure()) return result; | 254 if (result->IsFailure()) return result; |
242 } | 255 } |
243 return code; | 256 return code; |
244 } | 257 } |
245 | 258 |
246 | 259 |
247 Object* StubCache::ComputeKeyedLoadConstant(String* name, | 260 Object* StubCache::ComputeKeyedLoadConstant(String* name, |
248 JSObject* receiver, | 261 JSObject* receiver, |
249 JSObject* holder, | 262 JSObject* holder, |
250 Object* value) { | 263 Object* value) { |
| 264 ASSERT(IC::GetCodeCacheForObject(receiver, holder) == OWN_MAP); |
| 265 Map* map = receiver->map(); |
251 Code::Flags flags = | 266 Code::Flags flags = |
252 Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, CONSTANT_FUNCTION); | 267 Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, CONSTANT_FUNCTION); |
253 Object* code = receiver->map()->FindInCodeCache(name, flags); | 268 Object* code = map->FindInCodeCache(name, flags); |
254 if (code->IsUndefined()) { | 269 if (code->IsUndefined()) { |
255 KeyedLoadStubCompiler compiler; | 270 KeyedLoadStubCompiler compiler; |
256 code = compiler.CompileLoadConstant(name, receiver, holder, value); | 271 code = compiler.CompileLoadConstant(name, receiver, holder, value); |
257 if (code->IsFailure()) return code; | 272 if (code->IsFailure()) return code; |
258 PROFILE(CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, Code::cast(code), name)); | 273 PROFILE(CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, Code::cast(code), name)); |
259 Object* result = receiver->map()->UpdateCodeCache(name, Code::cast(code)); | 274 Object* result = map->UpdateCodeCache(name, Code::cast(code)); |
260 if (result->IsFailure()) return result; | 275 if (result->IsFailure()) return result; |
261 } | 276 } |
262 return code; | 277 return code; |
263 } | 278 } |
264 | 279 |
265 | 280 |
266 Object* StubCache::ComputeKeyedLoadInterceptor(String* name, | 281 Object* StubCache::ComputeKeyedLoadInterceptor(String* name, |
267 JSObject* receiver, | 282 JSObject* receiver, |
268 JSObject* holder) { | 283 JSObject* holder) { |
| 284 ASSERT(IC::GetCodeCacheForObject(receiver, holder) == OWN_MAP); |
| 285 Map* map = receiver->map(); |
269 Code::Flags flags = | 286 Code::Flags flags = |
270 Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, INTERCEPTOR); | 287 Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, INTERCEPTOR); |
271 Object* code = receiver->map()->FindInCodeCache(name, flags); | 288 Object* code = map->FindInCodeCache(name, flags); |
272 if (code->IsUndefined()) { | 289 if (code->IsUndefined()) { |
273 KeyedLoadStubCompiler compiler; | 290 KeyedLoadStubCompiler compiler; |
274 code = compiler.CompileLoadInterceptor(receiver, holder, name); | 291 code = compiler.CompileLoadInterceptor(receiver, holder, name); |
275 if (code->IsFailure()) return code; | 292 if (code->IsFailure()) return code; |
276 PROFILE(CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, Code::cast(code), name)); | 293 PROFILE(CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, Code::cast(code), name)); |
277 Object* result = receiver->map()->UpdateCodeCache(name, Code::cast(code)); | 294 Object* result = map->UpdateCodeCache(name, Code::cast(code)); |
278 if (result->IsFailure()) return result; | 295 if (result->IsFailure()) return result; |
279 } | 296 } |
280 return code; | 297 return code; |
281 } | 298 } |
282 | 299 |
283 | 300 |
284 Object* StubCache::ComputeKeyedLoadCallback(String* name, | 301 Object* StubCache::ComputeKeyedLoadCallback(String* name, |
285 JSObject* receiver, | 302 JSObject* receiver, |
286 JSObject* holder, | 303 JSObject* holder, |
287 AccessorInfo* callback) { | 304 AccessorInfo* callback) { |
| 305 ASSERT(IC::GetCodeCacheForObject(receiver, holder) == OWN_MAP); |
| 306 Map* map = receiver->map(); |
288 Code::Flags flags = | 307 Code::Flags flags = |
289 Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, CALLBACKS); | 308 Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, CALLBACKS); |
290 Object* code = receiver->map()->FindInCodeCache(name, flags); | 309 Object* code = map->FindInCodeCache(name, flags); |
291 if (code->IsUndefined()) { | 310 if (code->IsUndefined()) { |
292 KeyedLoadStubCompiler compiler; | 311 KeyedLoadStubCompiler compiler; |
293 code = compiler.CompileLoadCallback(name, receiver, holder, callback); | 312 code = compiler.CompileLoadCallback(name, receiver, holder, callback); |
294 if (code->IsFailure()) return code; | 313 if (code->IsFailure()) return code; |
295 PROFILE(CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, Code::cast(code), name)); | 314 PROFILE(CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, Code::cast(code), name)); |
296 Object* result = receiver->map()->UpdateCodeCache(name, Code::cast(code)); | 315 Object* result = map->UpdateCodeCache(name, Code::cast(code)); |
297 if (result->IsFailure()) return result; | 316 if (result->IsFailure()) return result; |
298 } | 317 } |
299 return code; | 318 return code; |
300 } | 319 } |
301 | 320 |
302 | 321 |
303 | 322 |
304 Object* StubCache::ComputeKeyedLoadArrayLength(String* name, | 323 Object* StubCache::ComputeKeyedLoadArrayLength(String* name, |
305 JSArray* receiver) { | 324 JSArray* receiver) { |
306 Code::Flags flags = | 325 Code::Flags flags = |
307 Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, CALLBACKS); | 326 Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, CALLBACKS); |
308 Object* code = receiver->map()->FindInCodeCache(name, flags); | 327 ASSERT(receiver->IsJSObject()); |
| 328 Map* map = receiver->map(); |
| 329 Object* code = map->FindInCodeCache(name, flags); |
309 if (code->IsUndefined()) { | 330 if (code->IsUndefined()) { |
310 KeyedLoadStubCompiler compiler; | 331 KeyedLoadStubCompiler compiler; |
311 code = compiler.CompileLoadArrayLength(name); | 332 code = compiler.CompileLoadArrayLength(name); |
312 if (code->IsFailure()) return code; | 333 if (code->IsFailure()) return code; |
313 PROFILE(CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, Code::cast(code), name)); | 334 PROFILE(CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, Code::cast(code), name)); |
314 Object* result = receiver->map()->UpdateCodeCache(name, Code::cast(code)); | 335 Object* result = map->UpdateCodeCache(name, Code::cast(code)); |
315 if (result->IsFailure()) return result; | 336 if (result->IsFailure()) return result; |
316 } | 337 } |
317 return code; | 338 return code; |
318 } | 339 } |
319 | 340 |
320 | 341 |
321 Object* StubCache::ComputeKeyedLoadStringLength(String* name, | 342 Object* StubCache::ComputeKeyedLoadStringLength(String* name, |
322 String* receiver) { | 343 String* receiver) { |
323 Code::Flags flags = | 344 Code::Flags flags = |
324 Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, CALLBACKS); | 345 Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, CALLBACKS); |
325 Object* code = receiver->map()->FindInCodeCache(name, flags); | 346 Map* map = receiver->map(); |
| 347 Object* code = map->FindInCodeCache(name, flags); |
326 if (code->IsUndefined()) { | 348 if (code->IsUndefined()) { |
327 KeyedLoadStubCompiler compiler; | 349 KeyedLoadStubCompiler compiler; |
328 code = compiler.CompileLoadStringLength(name); | 350 code = compiler.CompileLoadStringLength(name); |
329 if (code->IsFailure()) return code; | 351 if (code->IsFailure()) return code; |
330 PROFILE(CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, Code::cast(code), name)); | 352 PROFILE(CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, Code::cast(code), name)); |
331 Object* result = receiver->map()->UpdateCodeCache(name, Code::cast(code)); | 353 Object* result = map->UpdateCodeCache(name, Code::cast(code)); |
332 if (result->IsFailure()) return result; | 354 if (result->IsFailure()) return result; |
333 } | 355 } |
334 return code; | 356 return code; |
335 } | 357 } |
336 | 358 |
337 | 359 |
338 Object* StubCache::ComputeKeyedLoadFunctionPrototype(String* name, | 360 Object* StubCache::ComputeKeyedLoadFunctionPrototype(String* name, |
339 JSFunction* receiver) { | 361 JSFunction* receiver) { |
340 Code::Flags flags = | 362 Code::Flags flags = |
341 Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, CALLBACKS); | 363 Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC, CALLBACKS); |
342 Object* code = receiver->map()->FindInCodeCache(name, flags); | 364 Map* map = receiver->map(); |
| 365 Object* code = map->FindInCodeCache(name, flags); |
343 if (code->IsUndefined()) { | 366 if (code->IsUndefined()) { |
344 KeyedLoadStubCompiler compiler; | 367 KeyedLoadStubCompiler compiler; |
345 code = compiler.CompileLoadFunctionPrototype(name); | 368 code = compiler.CompileLoadFunctionPrototype(name); |
346 if (code->IsFailure()) return code; | 369 if (code->IsFailure()) return code; |
347 PROFILE(CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, Code::cast(code), name)); | 370 PROFILE(CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG, Code::cast(code), name)); |
348 Object* result = receiver->map()->UpdateCodeCache(name, Code::cast(code)); | 371 Object* result = map->UpdateCodeCache(name, Code::cast(code)); |
349 if (result->IsFailure()) return result; | 372 if (result->IsFailure()) return result; |
350 } | 373 } |
351 return code; | 374 return code; |
352 } | 375 } |
353 | 376 |
354 | 377 |
355 Object* StubCache::ComputeStoreField(String* name, | 378 Object* StubCache::ComputeStoreField(String* name, |
356 JSObject* receiver, | 379 JSObject* receiver, |
357 int field_index, | 380 int field_index, |
358 Map* transition) { | 381 Map* transition) { |
(...skipping 19 matching lines...) Expand all Loading... |
378 | 401 |
379 Object* StubCache::ComputeStoreGlobal(String* name, | 402 Object* StubCache::ComputeStoreGlobal(String* name, |
380 GlobalObject* receiver, | 403 GlobalObject* receiver, |
381 JSGlobalPropertyCell* cell) { | 404 JSGlobalPropertyCell* cell) { |
382 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::STORE_IC, NORMAL); | 405 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::STORE_IC, NORMAL); |
383 Object* code = receiver->map()->FindInCodeCache(name, flags); | 406 Object* code = receiver->map()->FindInCodeCache(name, flags); |
384 if (code->IsUndefined()) { | 407 if (code->IsUndefined()) { |
385 StoreStubCompiler compiler; | 408 StoreStubCompiler compiler; |
386 code = compiler.CompileStoreGlobal(receiver, cell, name); | 409 code = compiler.CompileStoreGlobal(receiver, cell, name); |
387 if (code->IsFailure()) return code; | 410 if (code->IsFailure()) return code; |
388 PROFILE(CodeCreateEvent(Logger::LOAD_IC_TAG, Code::cast(code), name)); | 411 PROFILE(CodeCreateEvent(Logger::STORE_IC_TAG, Code::cast(code), name)); |
389 Object* result = receiver->map()->UpdateCodeCache(name, Code::cast(code)); | 412 Object* result = receiver->map()->UpdateCodeCache(name, Code::cast(code)); |
390 if (result->IsFailure()) return result; | 413 if (result->IsFailure()) return result; |
391 } | 414 } |
392 return code; | 415 return code; |
393 } | 416 } |
394 | 417 |
395 | 418 |
396 Object* StubCache::ComputeStoreCallback(String* name, | 419 Object* StubCache::ComputeStoreCallback(String* name, |
397 JSObject* receiver, | 420 JSObject* receiver, |
398 AccessorInfo* callback) { | 421 AccessorInfo* callback) { |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
449 (kind == Code::CALL_IC ? Logger::type : Logger::KEYED_##type) | 472 (kind == Code::CALL_IC ? Logger::type : Logger::KEYED_##type) |
450 | 473 |
451 Object* StubCache::ComputeCallConstant(int argc, | 474 Object* StubCache::ComputeCallConstant(int argc, |
452 InLoopFlag in_loop, | 475 InLoopFlag in_loop, |
453 Code::Kind kind, | 476 Code::Kind kind, |
454 String* name, | 477 String* name, |
455 Object* object, | 478 Object* object, |
456 JSObject* holder, | 479 JSObject* holder, |
457 JSFunction* function) { | 480 JSFunction* function) { |
458 // Compute the check type and the map. | 481 // Compute the check type and the map. |
459 Map* map = IC::GetCodeCacheMapForObject(object); | 482 InlineCacheHolderFlag cache_holder = |
| 483 IC::GetCodeCacheForObject(object, holder); |
| 484 Map* map = IC::GetCodeCacheMap(object, cache_holder); |
460 | 485 |
461 // Compute check type based on receiver/holder. | 486 // Compute check type based on receiver/holder. |
462 StubCompiler::CheckType check = StubCompiler::RECEIVER_MAP_CHECK; | 487 StubCompiler::CheckType check = StubCompiler::RECEIVER_MAP_CHECK; |
463 if (object->IsString()) { | 488 if (object->IsString()) { |
464 check = StubCompiler::STRING_CHECK; | 489 check = StubCompiler::STRING_CHECK; |
465 } else if (object->IsNumber()) { | 490 } else if (object->IsNumber()) { |
466 check = StubCompiler::NUMBER_CHECK; | 491 check = StubCompiler::NUMBER_CHECK; |
467 } else if (object->IsBoolean()) { | 492 } else if (object->IsBoolean()) { |
468 check = StubCompiler::BOOLEAN_CHECK; | 493 check = StubCompiler::BOOLEAN_CHECK; |
469 } | 494 } |
470 | 495 |
471 Code::Flags flags = | 496 Code::Flags flags = |
472 Code::ComputeMonomorphicFlags(kind, | 497 Code::ComputeMonomorphicFlags(kind, |
473 CONSTANT_FUNCTION, | 498 CONSTANT_FUNCTION, |
| 499 cache_holder, |
474 in_loop, | 500 in_loop, |
475 argc); | 501 argc); |
476 Object* code = map->FindInCodeCache(name, flags); | 502 Object* code = map->FindInCodeCache(name, flags); |
477 if (code->IsUndefined()) { | 503 if (code->IsUndefined()) { |
478 // If the function hasn't been compiled yet, we cannot do it now | 504 // If the function hasn't been compiled yet, we cannot do it now |
479 // because it may cause GC. To avoid this issue, we return an | 505 // because it may cause GC. To avoid this issue, we return an |
480 // internal error which will make sure we do not update any | 506 // internal error which will make sure we do not update any |
481 // caches. | 507 // caches. |
482 if (!function->is_compiled()) return Failure::InternalError(); | 508 if (!function->is_compiled()) return Failure::InternalError(); |
483 // Compile the stub - only create stubs for fully compiled functions. | 509 // Compile the stub - only create stubs for fully compiled functions. |
484 CallStubCompiler compiler(argc, in_loop, kind); | 510 CallStubCompiler compiler(argc, in_loop, kind, cache_holder); |
485 code = compiler.CompileCallConstant(object, holder, function, name, check); | 511 code = compiler.CompileCallConstant(object, holder, function, name, check); |
486 if (code->IsFailure()) return code; | 512 if (code->IsFailure()) return code; |
487 ASSERT_EQ(flags, Code::cast(code)->flags()); | 513 ASSERT_EQ(flags, Code::cast(code)->flags()); |
488 PROFILE(CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG), | 514 PROFILE(CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG), |
489 Code::cast(code), name)); | 515 Code::cast(code), name)); |
490 Object* result = map->UpdateCodeCache(name, Code::cast(code)); | 516 Object* result = map->UpdateCodeCache(name, Code::cast(code)); |
491 if (result->IsFailure()) return result; | 517 if (result->IsFailure()) return result; |
492 } | 518 } |
493 return code; | 519 return code; |
494 } | 520 } |
495 | 521 |
496 | 522 |
497 Object* StubCache::ComputeCallField(int argc, | 523 Object* StubCache::ComputeCallField(int argc, |
498 InLoopFlag in_loop, | 524 InLoopFlag in_loop, |
499 Code::Kind kind, | 525 Code::Kind kind, |
500 String* name, | 526 String* name, |
501 Object* object, | 527 Object* object, |
502 JSObject* holder, | 528 JSObject* holder, |
503 int index) { | 529 int index) { |
504 // Compute the check type and the map. | 530 // Compute the check type and the map. |
505 Map* map = IC::GetCodeCacheMapForObject(object); | 531 InlineCacheHolderFlag cache_holder = |
| 532 IC::GetCodeCacheForObject(object, holder); |
| 533 Map* map = IC::GetCodeCacheMap(object, cache_holder); |
506 | 534 |
507 // TODO(1233596): We cannot do receiver map check for non-JS objects | 535 // TODO(1233596): We cannot do receiver map check for non-JS objects |
508 // because they may be represented as immediates without a | 536 // because they may be represented as immediates without a |
509 // map. Instead, we check against the map in the holder. | 537 // map. Instead, we check against the map in the holder. |
510 if (object->IsNumber() || object->IsBoolean() || object->IsString()) { | 538 if (object->IsNumber() || object->IsBoolean() || object->IsString()) { |
511 object = holder; | 539 object = holder; |
512 } | 540 } |
513 | 541 |
514 Code::Flags flags = Code::ComputeMonomorphicFlags(kind, | 542 Code::Flags flags = Code::ComputeMonomorphicFlags(kind, |
515 FIELD, | 543 FIELD, |
| 544 cache_holder, |
516 in_loop, | 545 in_loop, |
517 argc); | 546 argc); |
518 Object* code = map->FindInCodeCache(name, flags); | 547 Object* code = map->FindInCodeCache(name, flags); |
519 if (code->IsUndefined()) { | 548 if (code->IsUndefined()) { |
520 CallStubCompiler compiler(argc, in_loop, kind); | 549 CallStubCompiler compiler(argc, in_loop, kind, cache_holder); |
521 code = compiler.CompileCallField(JSObject::cast(object), | 550 code = compiler.CompileCallField(JSObject::cast(object), |
522 holder, | 551 holder, |
523 index, | 552 index, |
524 name); | 553 name); |
525 if (code->IsFailure()) return code; | 554 if (code->IsFailure()) return code; |
526 ASSERT_EQ(flags, Code::cast(code)->flags()); | 555 ASSERT_EQ(flags, Code::cast(code)->flags()); |
527 PROFILE(CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG), | 556 PROFILE(CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG), |
528 Code::cast(code), name)); | 557 Code::cast(code), name)); |
529 Object* result = map->UpdateCodeCache(name, Code::cast(code)); | 558 Object* result = map->UpdateCodeCache(name, Code::cast(code)); |
530 if (result->IsFailure()) return result; | 559 if (result->IsFailure()) return result; |
531 } | 560 } |
532 return code; | 561 return code; |
533 } | 562 } |
534 | 563 |
535 | 564 |
536 Object* StubCache::ComputeCallInterceptor(int argc, | 565 Object* StubCache::ComputeCallInterceptor(int argc, |
537 Code::Kind kind, | 566 Code::Kind kind, |
538 String* name, | 567 String* name, |
539 Object* object, | 568 Object* object, |
540 JSObject* holder) { | 569 JSObject* holder) { |
541 // Compute the check type and the map. | 570 // Compute the check type and the map. |
542 // If the object is a value, we use the prototype map for the cache. | 571 InlineCacheHolderFlag cache_holder = |
543 Map* map = IC::GetCodeCacheMapForObject(object); | 572 IC::GetCodeCacheForObject(object, holder); |
| 573 Map* map = IC::GetCodeCacheMap(object, cache_holder); |
544 | 574 |
545 // TODO(1233596): We cannot do receiver map check for non-JS objects | 575 // TODO(1233596): We cannot do receiver map check for non-JS objects |
546 // because they may be represented as immediates without a | 576 // because they may be represented as immediates without a |
547 // map. Instead, we check against the map in the holder. | 577 // map. Instead, we check against the map in the holder. |
548 if (object->IsNumber() || object->IsBoolean() || object->IsString()) { | 578 if (object->IsNumber() || object->IsBoolean() || object->IsString()) { |
549 object = holder; | 579 object = holder; |
550 } | 580 } |
551 | 581 |
552 Code::Flags flags = | 582 Code::Flags flags = |
553 Code::ComputeMonomorphicFlags(kind, | 583 Code::ComputeMonomorphicFlags(kind, |
554 INTERCEPTOR, | 584 INTERCEPTOR, |
| 585 cache_holder, |
555 NOT_IN_LOOP, | 586 NOT_IN_LOOP, |
556 argc); | 587 argc); |
557 Object* code = map->FindInCodeCache(name, flags); | 588 Object* code = map->FindInCodeCache(name, flags); |
558 if (code->IsUndefined()) { | 589 if (code->IsUndefined()) { |
559 CallStubCompiler compiler(argc, NOT_IN_LOOP, kind); | 590 CallStubCompiler compiler(argc, NOT_IN_LOOP, kind, cache_holder); |
560 code = compiler.CompileCallInterceptor(JSObject::cast(object), | 591 code = compiler.CompileCallInterceptor(JSObject::cast(object), |
561 holder, | 592 holder, |
562 name); | 593 name); |
563 if (code->IsFailure()) return code; | 594 if (code->IsFailure()) return code; |
564 ASSERT_EQ(flags, Code::cast(code)->flags()); | 595 ASSERT_EQ(flags, Code::cast(code)->flags()); |
565 PROFILE(CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG), | 596 PROFILE(CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG), |
566 Code::cast(code), name)); | 597 Code::cast(code), name)); |
567 Object* result = map->UpdateCodeCache(name, Code::cast(code)); | 598 Object* result = map->UpdateCodeCache(name, Code::cast(code)); |
568 if (result->IsFailure()) return result; | 599 if (result->IsFailure()) return result; |
569 } | 600 } |
(...skipping 13 matching lines...) Expand all Loading... |
583 | 614 |
584 | 615 |
585 Object* StubCache::ComputeCallGlobal(int argc, | 616 Object* StubCache::ComputeCallGlobal(int argc, |
586 InLoopFlag in_loop, | 617 InLoopFlag in_loop, |
587 Code::Kind kind, | 618 Code::Kind kind, |
588 String* name, | 619 String* name, |
589 JSObject* receiver, | 620 JSObject* receiver, |
590 GlobalObject* holder, | 621 GlobalObject* holder, |
591 JSGlobalPropertyCell* cell, | 622 JSGlobalPropertyCell* cell, |
592 JSFunction* function) { | 623 JSFunction* function) { |
| 624 InlineCacheHolderFlag cache_holder = |
| 625 IC::GetCodeCacheForObject(receiver, holder); |
| 626 Map* map = IC::GetCodeCacheMap(receiver, cache_holder); |
593 Code::Flags flags = | 627 Code::Flags flags = |
594 Code::ComputeMonomorphicFlags(kind, | 628 Code::ComputeMonomorphicFlags(kind, |
595 NORMAL, | 629 NORMAL, |
| 630 cache_holder, |
596 in_loop, | 631 in_loop, |
597 argc); | 632 argc); |
598 Object* code = receiver->map()->FindInCodeCache(name, flags); | 633 Object* code = map->FindInCodeCache(name, flags); |
599 if (code->IsUndefined()) { | 634 if (code->IsUndefined()) { |
600 // If the function hasn't been compiled yet, we cannot do it now | 635 // If the function hasn't been compiled yet, we cannot do it now |
601 // because it may cause GC. To avoid this issue, we return an | 636 // because it may cause GC. To avoid this issue, we return an |
602 // internal error which will make sure we do not update any | 637 // internal error which will make sure we do not update any |
603 // caches. | 638 // caches. |
604 if (!function->is_compiled()) return Failure::InternalError(); | 639 if (!function->is_compiled()) return Failure::InternalError(); |
605 CallStubCompiler compiler(argc, in_loop, kind); | 640 CallStubCompiler compiler(argc, in_loop, kind, cache_holder); |
606 code = compiler.CompileCallGlobal(receiver, holder, cell, function, name); | 641 code = compiler.CompileCallGlobal(receiver, holder, cell, function, name); |
607 if (code->IsFailure()) return code; | 642 if (code->IsFailure()) return code; |
608 ASSERT_EQ(flags, Code::cast(code)->flags()); | 643 ASSERT_EQ(flags, Code::cast(code)->flags()); |
609 PROFILE(CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG), | 644 PROFILE(CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG), |
610 Code::cast(code), name)); | 645 Code::cast(code), name)); |
611 Object* result = receiver->map()->UpdateCodeCache(name, Code::cast(code)); | 646 Object* result = map->UpdateCodeCache(name, Code::cast(code)); |
612 if (result->IsFailure()) return result; | 647 if (result->IsFailure()) return result; |
613 } | 648 } |
614 return code; | 649 return code; |
615 } | 650 } |
616 | 651 |
617 | 652 |
618 static Object* GetProbeValue(Code::Flags flags) { | 653 static Object* GetProbeValue(Code::Flags flags) { |
619 // Use raw_unchecked... so we don't get assert failures during GC. | 654 // Use raw_unchecked... so we don't get assert failures during GC. |
620 NumberDictionary* dictionary = Heap::raw_unchecked_non_monomorphic_cache(); | 655 NumberDictionary* dictionary = Heap::raw_unchecked_non_monomorphic_cache(); |
621 int entry = dictionary->FindEntry(flags); | 656 int entry = dictionary->FindEntry(flags); |
(...skipping 579 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1201 return GetCodeWithFlags(flags, name); | 1236 return GetCodeWithFlags(flags, name); |
1202 } | 1237 } |
1203 | 1238 |
1204 | 1239 |
1205 Object* KeyedStoreStubCompiler::GetCode(PropertyType type, String* name) { | 1240 Object* KeyedStoreStubCompiler::GetCode(PropertyType type, String* name) { |
1206 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::KEYED_STORE_IC, type); | 1241 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::KEYED_STORE_IC, type); |
1207 return GetCodeWithFlags(flags, name); | 1242 return GetCodeWithFlags(flags, name); |
1208 } | 1243 } |
1209 | 1244 |
1210 | 1245 |
| 1246 CallStubCompiler::CallStubCompiler(int argc, |
| 1247 InLoopFlag in_loop, |
| 1248 Code::Kind kind, |
| 1249 InlineCacheHolderFlag cache_holder) |
| 1250 : arguments_(argc) |
| 1251 , in_loop_(in_loop) |
| 1252 , kind_(kind) |
| 1253 , cache_holder_(cache_holder) { |
| 1254 } |
| 1255 |
| 1256 |
1211 Object* CallStubCompiler::CompileCustomCall(int generator_id, | 1257 Object* CallStubCompiler::CompileCustomCall(int generator_id, |
1212 Object* object, | 1258 Object* object, |
1213 JSObject* holder, | 1259 JSObject* holder, |
1214 JSFunction* function, | 1260 JSFunction* function, |
1215 String* fname, | 1261 String* fname, |
1216 CheckType check) { | 1262 CheckType check) { |
1217 ASSERT(generator_id >= 0 && generator_id < kNumCallGenerators); | 1263 ASSERT(generator_id >= 0 && generator_id < kNumCallGenerators); |
1218 switch (generator_id) { | 1264 switch (generator_id) { |
1219 #define CALL_GENERATOR_CASE(ignored1, ignored2, name) \ | 1265 #define CALL_GENERATOR_CASE(ignored1, ignored2, name) \ |
1220 case k##name##CallGenerator: \ | 1266 case k##name##CallGenerator: \ |
1221 return CallStubCompiler::Compile##name##Call(object, \ | 1267 return CallStubCompiler::Compile##name##Call(object, \ |
1222 holder, \ | 1268 holder, \ |
1223 function, \ | 1269 function, \ |
1224 fname, \ | 1270 fname, \ |
1225 check); | 1271 check); |
1226 CUSTOM_CALL_IC_GENERATORS(CALL_GENERATOR_CASE) | 1272 CUSTOM_CALL_IC_GENERATORS(CALL_GENERATOR_CASE) |
1227 #undef CALL_GENERATOR_CASE | 1273 #undef CALL_GENERATOR_CASE |
1228 } | 1274 } |
1229 UNREACHABLE(); | 1275 UNREACHABLE(); |
1230 return Heap::undefined_value(); | 1276 return Heap::undefined_value(); |
1231 } | 1277 } |
1232 | 1278 |
1233 | 1279 |
1234 Object* CallStubCompiler::GetCode(PropertyType type, String* name) { | 1280 Object* CallStubCompiler::GetCode(PropertyType type, String* name) { |
1235 int argc = arguments_.immediate(); | 1281 int argc = arguments_.immediate(); |
1236 Code::Flags flags = Code::ComputeMonomorphicFlags(kind_, | 1282 Code::Flags flags = Code::ComputeMonomorphicFlags(kind_, |
1237 type, | 1283 type, |
| 1284 cache_holder_, |
1238 in_loop_, | 1285 in_loop_, |
1239 argc); | 1286 argc); |
1240 return GetCodeWithFlags(flags, name); | 1287 return GetCodeWithFlags(flags, name); |
1241 } | 1288 } |
1242 | 1289 |
1243 | 1290 |
1244 Object* CallStubCompiler::GetCode(JSFunction* function) { | 1291 Object* CallStubCompiler::GetCode(JSFunction* function) { |
1245 String* function_name = NULL; | 1292 String* function_name = NULL; |
1246 if (function->shared()->name()->IsString()) { | 1293 if (function->shared()->name()->IsString()) { |
1247 function_name = String::cast(function->shared()->name()); | 1294 function_name = String::cast(function->shared()->name()); |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1323 expected_receiver_type_ = | 1370 expected_receiver_type_ = |
1324 FunctionTemplateInfo::cast(signature->receiver()); | 1371 FunctionTemplateInfo::cast(signature->receiver()); |
1325 } | 1372 } |
1326 } | 1373 } |
1327 | 1374 |
1328 is_simple_api_call_ = true; | 1375 is_simple_api_call_ = true; |
1329 } | 1376 } |
1330 | 1377 |
1331 | 1378 |
1332 } } // namespace v8::internal | 1379 } } // namespace v8::internal |
OLD | NEW |