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 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
188 current_map = handle(Handle<HeapObject>::cast(next)->map()); | 188 current_map = handle(Handle<HeapObject>::cast(next)->map()); |
189 if (current_map->is_dictionary_map()) cache_name = name; | 189 if (current_map->is_dictionary_map()) cache_name = name; |
190 } | 190 } |
191 | 191 |
192 // Compile the stub that is either shared for all names or | 192 // Compile the stub that is either shared for all names or |
193 // name specific if there are global objects involved. | 193 // name specific if there are global objects involved. |
194 Handle<Code> handler = FindHandler( | 194 Handle<Code> handler = FindHandler( |
195 cache_name, stub_holder, Code::LOAD_IC, flag); | 195 cache_name, stub_holder, Code::LOAD_IC, flag); |
196 if (!handler.is_null()) return handler; | 196 if (!handler.is_null()) return handler; |
197 | 197 |
198 LoadStubCompiler compiler(isolate_, flag); | 198 LoadStubCompiler compiler(isolate_, kNoExtraICState, flag); |
199 handler = compiler.CompileLoadNonexistent(type, last, cache_name); | 199 handler = compiler.CompileLoadNonexistent(type, last, cache_name); |
200 Map::UpdateCodeCache(stub_holder, cache_name, handler); | 200 Map::UpdateCodeCache(stub_holder, cache_name, handler); |
201 return handler; | 201 return handler; |
202 } | 202 } |
203 | 203 |
204 | 204 |
205 Handle<Code> StubCache::ComputeKeyedLoadElement(Handle<Map> receiver_map) { | 205 Handle<Code> StubCache::ComputeKeyedLoadElement(Handle<Map> receiver_map) { |
206 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC); | 206 Code::Flags flags = Code::ComputeMonomorphicFlags(Code::KEYED_LOAD_IC); |
207 Handle<Name> name = | 207 Handle<Name> name = |
208 isolate()->factory()->KeyedLoadElementMonomorphic_string(); | 208 isolate()->factory()->KeyedLoadElementMonomorphic_string(); |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
240 KeyedStoreStubCompiler compiler(isolate(), extra_state); | 240 KeyedStoreStubCompiler compiler(isolate(), extra_state); |
241 Handle<Code> code = compiler.CompileStoreElement(receiver_map); | 241 Handle<Code> code = compiler.CompileStoreElement(receiver_map); |
242 | 242 |
243 Map::UpdateCodeCache(receiver_map, name, code); | 243 Map::UpdateCodeCache(receiver_map, name, code); |
244 ASSERT(KeyedStoreIC::GetKeyedAccessStoreMode(code->extra_ic_state()) | 244 ASSERT(KeyedStoreIC::GetKeyedAccessStoreMode(code->extra_ic_state()) |
245 == store_mode); | 245 == store_mode); |
246 return code; | 246 return code; |
247 } | 247 } |
248 | 248 |
249 | 249 |
250 #define CALL_LOGGER_TAG(kind, type) \ | 250 #define CALL_LOGGER_TAG(kind, type) (Logger::KEYED_##type) |
251 (kind == Code::CALL_IC ? Logger::type : Logger::KEYED_##type) | |
252 | |
253 Handle<Code> StubCache::ComputeCallConstant(int argc, | |
254 Code::Kind kind, | |
255 ExtraICState extra_state, | |
256 Handle<Name> name, | |
257 Handle<Object> object, | |
258 Handle<JSObject> holder, | |
259 Handle<JSFunction> function) { | |
260 // Compute the check type and the map. | |
261 InlineCacheHolderFlag cache_holder = IC::GetCodeCacheForObject(*object); | |
262 Handle<HeapObject> stub_holder(IC::GetCodeCacheHolder( | |
263 isolate_, *object, cache_holder)); | |
264 | |
265 // Compute check type based on receiver/holder. | |
266 CheckType check = RECEIVER_MAP_CHECK; | |
267 if (object->IsString()) { | |
268 check = STRING_CHECK; | |
269 } else if (object->IsSymbol()) { | |
270 check = SYMBOL_CHECK; | |
271 } else if (object->IsNumber()) { | |
272 check = NUMBER_CHECK; | |
273 } else if (object->IsBoolean()) { | |
274 check = BOOLEAN_CHECK; | |
275 } | |
276 | |
277 if (check != RECEIVER_MAP_CHECK && | |
278 !function->IsBuiltin() && | |
279 function->shared()->is_classic_mode()) { | |
280 // Calling non-strict non-builtins with a value as the receiver | |
281 // requires boxing. | |
282 return Handle<Code>::null(); | |
283 } | |
284 | |
285 Code::Flags flags = Code::ComputeMonomorphicFlags( | |
286 kind, extra_state, cache_holder, Code::FAST, argc); | |
287 Handle<Object> probe(stub_holder->map()->FindInCodeCache(*name, flags), | |
288 isolate_); | |
289 if (probe->IsCode()) return Handle<Code>::cast(probe); | |
290 | |
291 CallStubCompiler compiler(isolate_, argc, kind, extra_state, cache_holder); | |
292 Handle<Code> code = | |
293 compiler.CompileCallConstant(object, holder, name, check, function); | |
294 code->set_check_type(check); | |
295 ASSERT(flags == code->flags()); | |
296 PROFILE(isolate_, | |
297 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG), *code, *name)); | |
298 GDBJIT(AddCode(GDBJITInterface::CALL_IC, *name, *code)); | |
299 | |
300 HeapObject::UpdateMapCodeCache(stub_holder, name, code); | |
301 return code; | |
302 } | |
303 | |
304 | |
305 Handle<Code> StubCache::ComputeCallField(int argc, | |
306 Code::Kind kind, | |
307 ExtraICState extra_state, | |
308 Handle<Name> name, | |
309 Handle<Object> object, | |
310 Handle<JSObject> holder, | |
311 PropertyIndex index) { | |
312 // Compute the check type and the map. | |
313 InlineCacheHolderFlag cache_holder = IC::GetCodeCacheForObject(*object); | |
314 Handle<HeapObject> stub_holder(IC::GetCodeCacheHolder( | |
315 isolate_, *object, cache_holder)); | |
316 | |
317 // TODO(1233596): We cannot do receiver map check for non-JS objects | |
318 // because they may be represented as immediates without a | |
319 // map. Instead, we check against the map in the holder. | |
320 if (object->IsNumber() || object->IsSymbol() || | |
321 object->IsBoolean() || object->IsString()) { | |
322 object = holder; | |
323 } | |
324 | |
325 Code::Flags flags = Code::ComputeMonomorphicFlags( | |
326 kind, extra_state, cache_holder, Code::FAST, argc); | |
327 Handle<Object> probe(stub_holder->map()->FindInCodeCache(*name, flags), | |
328 isolate_); | |
329 if (probe->IsCode()) return Handle<Code>::cast(probe); | |
330 | |
331 CallStubCompiler compiler(isolate_, argc, kind, extra_state, cache_holder); | |
332 Handle<Code> code = | |
333 compiler.CompileCallField(Handle<JSObject>::cast(object), | |
334 holder, index, name); | |
335 ASSERT(flags == code->flags()); | |
336 PROFILE(isolate_, | |
337 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG), *code, *name)); | |
338 GDBJIT(AddCode(GDBJITInterface::CALL_IC, *name, *code)); | |
339 HeapObject::UpdateMapCodeCache(stub_holder, name, code); | |
340 return code; | |
341 } | |
342 | |
343 | |
344 Handle<Code> StubCache::ComputeCallInterceptor(int argc, | |
345 Code::Kind kind, | |
346 ExtraICState extra_state, | |
347 Handle<Name> name, | |
348 Handle<Object> object, | |
349 Handle<JSObject> holder) { | |
350 // Compute the check type and the map. | |
351 InlineCacheHolderFlag cache_holder = IC::GetCodeCacheForObject(*object); | |
352 Handle<HeapObject> stub_holder(IC::GetCodeCacheHolder( | |
353 isolate_, *object, cache_holder)); | |
354 | |
355 // TODO(1233596): We cannot do receiver map check for non-JS objects | |
356 // because they may be represented as immediates without a | |
357 // map. Instead, we check against the map in the holder. | |
358 if (object->IsNumber() || object->IsSymbol() || | |
359 object->IsBoolean() || object->IsString()) { | |
360 object = holder; | |
361 } | |
362 | |
363 Code::Flags flags = Code::ComputeMonomorphicFlags( | |
364 kind, extra_state, cache_holder, Code::FAST, argc); | |
365 Handle<Object> probe(stub_holder->map()->FindInCodeCache(*name, flags), | |
366 isolate_); | |
367 if (probe->IsCode()) return Handle<Code>::cast(probe); | |
368 | |
369 CallStubCompiler compiler(isolate(), argc, kind, extra_state, cache_holder); | |
370 Handle<Code> code = | |
371 compiler.CompileCallInterceptor(Handle<JSObject>::cast(object), | |
372 holder, name); | |
373 ASSERT(flags == code->flags()); | |
374 PROFILE(isolate(), | |
375 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG), *code, *name)); | |
376 GDBJIT(AddCode(GDBJITInterface::CALL_IC, *name, *code)); | |
377 HeapObject::UpdateMapCodeCache(stub_holder, name, code); | |
378 return code; | |
379 } | |
380 | |
381 | |
382 Handle<Code> StubCache::ComputeCallGlobal(int argc, | |
383 Code::Kind kind, | |
384 ExtraICState extra_state, | |
385 Handle<Name> name, | |
386 Handle<JSObject> receiver, | |
387 Handle<GlobalObject> holder, | |
388 Handle<PropertyCell> cell, | |
389 Handle<JSFunction> function) { | |
390 Code::Flags flags = Code::ComputeMonomorphicFlags( | |
391 kind, extra_state, OWN_MAP, Code::NORMAL, argc); | |
392 Handle<Object> probe(receiver->map()->FindInCodeCache(*name, flags), | |
393 isolate_); | |
394 if (probe->IsCode()) return Handle<Code>::cast(probe); | |
395 | |
396 CallStubCompiler compiler(isolate(), argc, kind, extra_state); | |
397 Handle<Code> code = | |
398 compiler.CompileCallGlobal(receiver, holder, cell, function, name); | |
399 ASSERT(flags == code->flags()); | |
400 PROFILE(isolate(), | |
401 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_IC_TAG), *code, *name)); | |
402 GDBJIT(AddCode(GDBJITInterface::CALL_IC, *name, *code)); | |
403 HeapObject::UpdateMapCodeCache(receiver, name, code); | |
404 return code; | |
405 } | |
406 | |
407 | 251 |
408 static void FillCache(Isolate* isolate, Handle<Code> code) { | 252 static void FillCache(Isolate* isolate, Handle<Code> code) { |
409 Handle<UnseededNumberDictionary> dictionary = | 253 Handle<UnseededNumberDictionary> dictionary = |
410 UnseededNumberDictionary::Set(isolate->factory()->non_monomorphic_cache(), | 254 UnseededNumberDictionary::Set(isolate->factory()->non_monomorphic_cache(), |
411 code->flags(), | 255 code->flags(), |
412 code); | 256 code); |
413 isolate->heap()->public_set_non_monomorphic_cache(*dictionary); | 257 isolate->heap()->public_set_non_monomorphic_cache(*dictionary); |
414 } | 258 } |
415 | 259 |
416 | 260 |
417 Code* StubCache::FindCallInitialize(int argc, Code::Kind kind) { | |
418 Code::Flags flags = Code::ComputeFlags( | |
419 kind, UNINITIALIZED, kNoExtraICState, Code::NORMAL, argc); | |
420 UnseededNumberDictionary* dictionary = | |
421 isolate()->heap()->non_monomorphic_cache(); | |
422 int entry = dictionary->FindEntry(isolate(), flags); | |
423 ASSERT(entry != -1); | |
424 Object* code = dictionary->ValueAt(entry); | |
425 // This might be called during the marking phase of the collector | |
426 // hence the unchecked cast. | |
427 return reinterpret_cast<Code*>(code); | |
428 } | |
429 | |
430 | |
431 Code* StubCache::FindPreMonomorphicIC(Code::Kind kind, ExtraICState state) { | 261 Code* StubCache::FindPreMonomorphicIC(Code::Kind kind, ExtraICState state) { |
432 Code::Flags flags = Code::ComputeFlags(kind, PREMONOMORPHIC, state); | 262 Code::Flags flags = Code::ComputeFlags(kind, PREMONOMORPHIC, state); |
433 UnseededNumberDictionary* dictionary = | 263 UnseededNumberDictionary* dictionary = |
434 isolate()->heap()->non_monomorphic_cache(); | 264 isolate()->heap()->non_monomorphic_cache(); |
435 int entry = dictionary->FindEntry(isolate(), flags); | 265 int entry = dictionary->FindEntry(isolate(), flags); |
436 ASSERT(entry != -1); | 266 ASSERT(entry != -1); |
437 Object* code = dictionary->ValueAt(entry); | 267 Object* code = dictionary->ValueAt(entry); |
438 // This might be called during the marking phase of the collector | 268 // This might be called during the marking phase of the collector |
439 // hence the unchecked cast. | 269 // hence the unchecked cast. |
440 return reinterpret_cast<Code*>(code); | 270 return reinterpret_cast<Code*>(code); |
441 } | 271 } |
442 | 272 |
443 | 273 |
444 Handle<Code> StubCache::ComputeCallInitialize(int argc, Code::Kind kind) { | |
445 Code::Flags flags = Code::ComputeFlags( | |
446 kind, UNINITIALIZED, kNoExtraICState, Code::NORMAL, argc); | |
447 Handle<UnseededNumberDictionary> cache = | |
448 isolate_->factory()->non_monomorphic_cache(); | |
449 int entry = cache->FindEntry(isolate_, flags); | |
450 if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry))); | |
451 | |
452 StubCompiler compiler(isolate_); | |
453 Handle<Code> code = compiler.CompileCallInitialize(flags); | |
454 FillCache(isolate_, code); | |
455 return code; | |
456 } | |
457 | |
458 | |
459 Handle<Code> StubCache::ComputeCallInitialize(int argc) { | |
460 return ComputeCallInitialize(argc, Code::CALL_IC); | |
461 } | |
462 | |
463 | |
464 Handle<Code> StubCache::ComputeKeyedCallInitialize(int argc) { | |
465 return ComputeCallInitialize(argc, Code::KEYED_CALL_IC); | |
466 } | |
467 | |
468 | |
469 Handle<Code> StubCache::ComputeCallPreMonomorphic( | |
470 int argc, | |
471 Code::Kind kind, | |
472 ExtraICState extra_state) { | |
473 Code::Flags flags = | |
474 Code::ComputeFlags(kind, PREMONOMORPHIC, extra_state, Code::NORMAL, argc); | |
475 Handle<UnseededNumberDictionary> cache = | |
476 isolate_->factory()->non_monomorphic_cache(); | |
477 int entry = cache->FindEntry(isolate_, flags); | |
478 if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry))); | |
479 | |
480 StubCompiler compiler(isolate_); | |
481 Handle<Code> code = compiler.CompileCallPreMonomorphic(flags); | |
482 FillCache(isolate_, code); | |
483 return code; | |
484 } | |
485 | |
486 | |
487 Handle<Code> StubCache::ComputeCallNormal(int argc, | |
488 Code::Kind kind, | |
489 ExtraICState extra_state) { | |
490 Code::Flags flags = | |
491 Code::ComputeFlags(kind, MONOMORPHIC, extra_state, Code::NORMAL, argc); | |
492 Handle<UnseededNumberDictionary> cache = | |
493 isolate_->factory()->non_monomorphic_cache(); | |
494 int entry = cache->FindEntry(isolate_, flags); | |
495 if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry))); | |
496 | |
497 StubCompiler compiler(isolate_); | |
498 Handle<Code> code = compiler.CompileCallNormal(flags); | |
499 FillCache(isolate_, code); | |
500 return code; | |
501 } | |
502 | |
503 | |
504 Handle<Code> StubCache::ComputeCallArguments(int argc) { | |
505 Code::Flags flags = | |
506 Code::ComputeFlags(Code::KEYED_CALL_IC, MEGAMORPHIC, | |
507 kNoExtraICState, Code::NORMAL, argc); | |
508 Handle<UnseededNumberDictionary> cache = | |
509 isolate_->factory()->non_monomorphic_cache(); | |
510 int entry = cache->FindEntry(isolate_, flags); | |
511 if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry))); | |
512 | |
513 StubCompiler compiler(isolate_); | |
514 Handle<Code> code = compiler.CompileCallArguments(flags); | |
515 FillCache(isolate_, code); | |
516 return code; | |
517 } | |
518 | |
519 | |
520 Handle<Code> StubCache::ComputeCallMegamorphic( | |
521 int argc, | |
522 Code::Kind kind, | |
523 ExtraICState extra_state) { | |
524 Code::Flags flags = | |
525 Code::ComputeFlags(kind, MEGAMORPHIC, extra_state, | |
526 Code::NORMAL, argc); | |
527 Handle<UnseededNumberDictionary> cache = | |
528 isolate_->factory()->non_monomorphic_cache(); | |
529 int entry = cache->FindEntry(isolate_, flags); | |
530 if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry))); | |
531 | |
532 StubCompiler compiler(isolate_); | |
533 Handle<Code> code = compiler.CompileCallMegamorphic(flags); | |
534 FillCache(isolate_, code); | |
535 return code; | |
536 } | |
537 | |
538 | |
539 Handle<Code> StubCache::ComputeLoad(InlineCacheState ic_state, | 274 Handle<Code> StubCache::ComputeLoad(InlineCacheState ic_state, |
540 ExtraICState extra_state) { | 275 ExtraICState extra_state) { |
541 Code::Flags flags = Code::ComputeFlags(Code::LOAD_IC, ic_state, extra_state); | 276 Code::Flags flags = Code::ComputeFlags(Code::LOAD_IC, ic_state, extra_state); |
542 Handle<UnseededNumberDictionary> cache = | 277 Handle<UnseededNumberDictionary> cache = |
543 isolate_->factory()->non_monomorphic_cache(); | 278 isolate_->factory()->non_monomorphic_cache(); |
544 int entry = cache->FindEntry(isolate_, flags); | 279 int entry = cache->FindEntry(isolate_, flags); |
545 if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry))); | 280 if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry))); |
546 | 281 |
547 StubCompiler compiler(isolate_); | 282 StubCompiler compiler(isolate_); |
548 Handle<Code> code; | 283 Handle<Code> code; |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
580 code = compiler.CompileStoreMegamorphic(flags); | 315 code = compiler.CompileStoreMegamorphic(flags); |
581 } else { | 316 } else { |
582 UNREACHABLE(); | 317 UNREACHABLE(); |
583 } | 318 } |
584 | 319 |
585 FillCache(isolate_, code); | 320 FillCache(isolate_, code); |
586 return code; | 321 return code; |
587 } | 322 } |
588 | 323 |
589 | 324 |
590 Handle<Code> StubCache::ComputeCallMiss(int argc, | |
591 Code::Kind kind, | |
592 ExtraICState extra_state) { | |
593 // MONOMORPHIC_PROTOTYPE_FAILURE state is used to make sure that miss stubs | |
594 // and monomorphic stubs are not mixed up together in the stub cache. | |
595 Code::Flags flags = | |
596 Code::ComputeFlags(kind, MONOMORPHIC_PROTOTYPE_FAILURE, extra_state, | |
597 Code::NORMAL, argc, OWN_MAP); | |
598 Handle<UnseededNumberDictionary> cache = | |
599 isolate_->factory()->non_monomorphic_cache(); | |
600 int entry = cache->FindEntry(isolate_, flags); | |
601 if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry))); | |
602 | |
603 StubCompiler compiler(isolate_); | |
604 Handle<Code> code = compiler.CompileCallMiss(flags); | |
605 FillCache(isolate_, code); | |
606 return code; | |
607 } | |
608 | |
609 | |
610 Handle<Code> StubCache::ComputeCompareNil(Handle<Map> receiver_map, | 325 Handle<Code> StubCache::ComputeCompareNil(Handle<Map> receiver_map, |
611 CompareNilICStub& stub) { | 326 CompareNilICStub& stub) { |
612 Handle<String> name(isolate_->heap()->empty_string()); | 327 Handle<String> name(isolate_->heap()->empty_string()); |
613 if (!receiver_map->is_shared()) { | 328 if (!receiver_map->is_shared()) { |
614 Handle<Code> cached_ic = FindIC(name, receiver_map, Code::COMPARE_NIL_IC, | 329 Handle<Code> cached_ic = FindIC(name, receiver_map, Code::COMPARE_NIL_IC, |
615 stub.GetExtraICState()); | 330 stub.GetExtraICState()); |
616 if (!cached_ic.is_null()) return cached_ic; | 331 if (!cached_ic.is_null()) return cached_ic; |
617 } | 332 } |
618 | 333 |
619 Handle<Code> ic = stub.GetCodeCopyFromTemplate(isolate_); | 334 Handle<Code> ic = stub.GetCodeCopyFromTemplate(isolate_); |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
694 Handle<Object> probe = cache->Lookup(receiver_maps, flags); | 409 Handle<Object> probe = cache->Lookup(receiver_maps, flags); |
695 if (probe->IsCode()) return Handle<Code>::cast(probe); | 410 if (probe->IsCode()) return Handle<Code>::cast(probe); |
696 | 411 |
697 KeyedStoreStubCompiler compiler(isolate_, extra_state); | 412 KeyedStoreStubCompiler compiler(isolate_, extra_state); |
698 Handle<Code> code = compiler.CompileStoreElementPolymorphic(receiver_maps); | 413 Handle<Code> code = compiler.CompileStoreElementPolymorphic(receiver_maps); |
699 PolymorphicCodeCache::Update(cache, receiver_maps, flags, code); | 414 PolymorphicCodeCache::Update(cache, receiver_maps, flags, code); |
700 return code; | 415 return code; |
701 } | 416 } |
702 | 417 |
703 | 418 |
704 #ifdef ENABLE_DEBUGGER_SUPPORT | |
705 Handle<Code> StubCache::ComputeCallDebugBreak(int argc, | |
706 Code::Kind kind) { | |
707 // Extra IC state is irrelevant for debug break ICs. They jump to | |
708 // the actual call ic to carry out the work. | |
709 Code::Flags flags = | |
710 Code::ComputeFlags(kind, DEBUG_STUB, DEBUG_BREAK, | |
711 Code::NORMAL, argc); | |
712 Handle<UnseededNumberDictionary> cache = | |
713 isolate_->factory()->non_monomorphic_cache(); | |
714 int entry = cache->FindEntry(isolate_, flags); | |
715 if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry))); | |
716 | |
717 StubCompiler compiler(isolate_); | |
718 Handle<Code> code = compiler.CompileCallDebugBreak(flags); | |
719 FillCache(isolate_, code); | |
720 return code; | |
721 } | |
722 | |
723 | |
724 Handle<Code> StubCache::ComputeCallDebugPrepareStepIn(int argc, | |
725 Code::Kind kind) { | |
726 // Extra IC state is irrelevant for debug break ICs. They jump to | |
727 // the actual call ic to carry out the work. | |
728 Code::Flags flags = | |
729 Code::ComputeFlags(kind, DEBUG_STUB, DEBUG_PREPARE_STEP_IN, | |
730 Code::NORMAL, argc); | |
731 Handle<UnseededNumberDictionary> cache = | |
732 isolate_->factory()->non_monomorphic_cache(); | |
733 int entry = cache->FindEntry(isolate_, flags); | |
734 if (entry != -1) return Handle<Code>(Code::cast(cache->ValueAt(entry))); | |
735 | |
736 StubCompiler compiler(isolate_); | |
737 Handle<Code> code = compiler.CompileCallDebugPrepareStepIn(flags); | |
738 FillCache(isolate_, code); | |
739 return code; | |
740 } | |
741 #endif | |
742 | |
743 | |
744 void StubCache::Clear() { | 419 void StubCache::Clear() { |
745 Code* empty = isolate_->builtins()->builtin(Builtins::kIllegal); | 420 Code* empty = isolate_->builtins()->builtin(Builtins::kIllegal); |
746 for (int i = 0; i < kPrimaryTableSize; i++) { | 421 for (int i = 0; i < kPrimaryTableSize; i++) { |
747 primary_[i].key = heap()->empty_string(); | 422 primary_[i].key = heap()->empty_string(); |
748 primary_[i].map = NULL; | 423 primary_[i].map = NULL; |
749 primary_[i].value = empty; | 424 primary_[i].value = empty; |
750 } | 425 } |
751 for (int j = 0; j < kSecondaryTableSize; j++) { | 426 for (int j = 0; j < kSecondaryTableSize; j++) { |
752 secondary_[j].key = heap()->empty_string(); | 427 secondary_[j].key = heap()->empty_string(); |
753 secondary_[j].map = NULL; | 428 secondary_[j].map = NULL; |
(...skipping 233 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
987 | 662 |
988 | 663 |
989 RUNTIME_FUNCTION(MaybeObject*, KeyedLoadPropertyWithInterceptor) { | 664 RUNTIME_FUNCTION(MaybeObject*, KeyedLoadPropertyWithInterceptor) { |
990 JSObject* receiver = JSObject::cast(args[0]); | 665 JSObject* receiver = JSObject::cast(args[0]); |
991 ASSERT(args.smi_at(1) >= 0); | 666 ASSERT(args.smi_at(1) >= 0); |
992 uint32_t index = args.smi_at(1); | 667 uint32_t index = args.smi_at(1); |
993 return receiver->GetElementWithInterceptor(receiver, index); | 668 return receiver->GetElementWithInterceptor(receiver, index); |
994 } | 669 } |
995 | 670 |
996 | 671 |
997 Handle<Code> StubCompiler::CompileCallInitialize(Code::Flags flags) { | |
998 int argc = Code::ExtractArgumentsCountFromFlags(flags); | |
999 Code::Kind kind = Code::ExtractKindFromFlags(flags); | |
1000 ExtraICState extra_state = Code::ExtractExtraICStateFromFlags(flags); | |
1001 if (kind == Code::CALL_IC) { | |
1002 CallIC::GenerateInitialize(masm(), argc, extra_state); | |
1003 } else { | |
1004 KeyedCallIC::GenerateInitialize(masm(), argc); | |
1005 } | |
1006 Handle<Code> code = GetCodeWithFlags(flags, "CompileCallInitialize"); | |
1007 isolate()->counters()->call_initialize_stubs()->Increment(); | |
1008 PROFILE(isolate(), | |
1009 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_INITIALIZE_TAG), | |
1010 *code, code->arguments_count())); | |
1011 GDBJIT(AddCode(GDBJITInterface::CALL_INITIALIZE, *code)); | |
1012 return code; | |
1013 } | |
1014 | |
1015 | |
1016 Handle<Code> StubCompiler::CompileCallPreMonomorphic(Code::Flags flags) { | |
1017 int argc = Code::ExtractArgumentsCountFromFlags(flags); | |
1018 // The code of the PreMonomorphic stub is the same as the code | |
1019 // of the Initialized stub. They just differ on the code object flags. | |
1020 Code::Kind kind = Code::ExtractKindFromFlags(flags); | |
1021 ExtraICState extra_state = Code::ExtractExtraICStateFromFlags(flags); | |
1022 if (kind == Code::CALL_IC) { | |
1023 CallIC::GenerateInitialize(masm(), argc, extra_state); | |
1024 } else { | |
1025 KeyedCallIC::GenerateInitialize(masm(), argc); | |
1026 } | |
1027 Handle<Code> code = GetCodeWithFlags(flags, "CompileCallPreMonomorphic"); | |
1028 isolate()->counters()->call_premonomorphic_stubs()->Increment(); | |
1029 PROFILE(isolate(), | |
1030 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_PRE_MONOMORPHIC_TAG), | |
1031 *code, code->arguments_count())); | |
1032 GDBJIT(AddCode(GDBJITInterface::CALL_PRE_MONOMORPHIC, *code)); | |
1033 return code; | |
1034 } | |
1035 | |
1036 | |
1037 Handle<Code> StubCompiler::CompileCallNormal(Code::Flags flags) { | |
1038 int argc = Code::ExtractArgumentsCountFromFlags(flags); | |
1039 Code::Kind kind = Code::ExtractKindFromFlags(flags); | |
1040 if (kind == Code::CALL_IC) { | |
1041 CallIC::GenerateNormal(masm(), argc); | |
1042 } else { | |
1043 KeyedCallIC::GenerateNormal(masm(), argc); | |
1044 } | |
1045 Handle<Code> code = GetCodeWithFlags(flags, "CompileCallNormal"); | |
1046 isolate()->counters()->call_normal_stubs()->Increment(); | |
1047 PROFILE(isolate(), | |
1048 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_NORMAL_TAG), | |
1049 *code, code->arguments_count())); | |
1050 GDBJIT(AddCode(GDBJITInterface::CALL_NORMAL, *code)); | |
1051 return code; | |
1052 } | |
1053 | |
1054 | |
1055 Handle<Code> StubCompiler::CompileCallMegamorphic(Code::Flags flags) { | |
1056 int argc = Code::ExtractArgumentsCountFromFlags(flags); | |
1057 Code::Kind kind = Code::ExtractKindFromFlags(flags); | |
1058 ExtraICState extra_state = Code::ExtractExtraICStateFromFlags(flags); | |
1059 if (kind == Code::CALL_IC) { | |
1060 CallIC::GenerateMegamorphic(masm(), argc, extra_state); | |
1061 } else { | |
1062 KeyedCallIC::GenerateMegamorphic(masm(), argc); | |
1063 } | |
1064 Handle<Code> code = GetCodeWithFlags(flags, "CompileCallMegamorphic"); | |
1065 isolate()->counters()->call_megamorphic_stubs()->Increment(); | |
1066 PROFILE(isolate(), | |
1067 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_MEGAMORPHIC_TAG), | |
1068 *code, code->arguments_count())); | |
1069 GDBJIT(AddCode(GDBJITInterface::CALL_MEGAMORPHIC, *code)); | |
1070 return code; | |
1071 } | |
1072 | |
1073 | |
1074 Handle<Code> StubCompiler::CompileLoadInitialize(Code::Flags flags) { | 672 Handle<Code> StubCompiler::CompileLoadInitialize(Code::Flags flags) { |
1075 LoadIC::GenerateInitialize(masm()); | 673 LoadIC::GenerateInitialize(masm()); |
1076 Handle<Code> code = GetCodeWithFlags(flags, "CompileLoadInitialize"); | 674 Handle<Code> code = GetCodeWithFlags(flags, "CompileLoadInitialize"); |
1077 PROFILE(isolate(), | 675 PROFILE(isolate(), |
1078 CodeCreateEvent(Logger::LOAD_INITIALIZE_TAG, *code, 0)); | 676 CodeCreateEvent(Logger::LOAD_INITIALIZE_TAG, *code, 0)); |
1079 GDBJIT(AddCode(GDBJITInterface::LOAD_IC, *code)); | 677 GDBJIT(AddCode(GDBJITInterface::LOAD_IC, *code)); |
1080 return code; | 678 return code; |
1081 } | 679 } |
1082 | 680 |
1083 | 681 |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1139 ExtraICState extra_state = Code::ExtractExtraICStateFromFlags(flags); | 737 ExtraICState extra_state = Code::ExtractExtraICStateFromFlags(flags); |
1140 StoreIC::GenerateMegamorphic(masm(), extra_state); | 738 StoreIC::GenerateMegamorphic(masm(), extra_state); |
1141 Handle<Code> code = GetCodeWithFlags(flags, "CompileStoreMegamorphic"); | 739 Handle<Code> code = GetCodeWithFlags(flags, "CompileStoreMegamorphic"); |
1142 PROFILE(isolate(), | 740 PROFILE(isolate(), |
1143 CodeCreateEvent(Logger::STORE_MEGAMORPHIC_TAG, *code, 0)); | 741 CodeCreateEvent(Logger::STORE_MEGAMORPHIC_TAG, *code, 0)); |
1144 GDBJIT(AddCode(GDBJITInterface::STORE_IC, *code)); | 742 GDBJIT(AddCode(GDBJITInterface::STORE_IC, *code)); |
1145 return code; | 743 return code; |
1146 } | 744 } |
1147 | 745 |
1148 | 746 |
1149 Handle<Code> StubCompiler::CompileCallArguments(Code::Flags flags) { | |
1150 int argc = Code::ExtractArgumentsCountFromFlags(flags); | |
1151 KeyedCallIC::GenerateNonStrictArguments(masm(), argc); | |
1152 Handle<Code> code = GetCodeWithFlags(flags, "CompileCallArguments"); | |
1153 PROFILE(isolate(), | |
1154 CodeCreateEvent(CALL_LOGGER_TAG(Code::ExtractKindFromFlags(flags), | |
1155 CALL_MEGAMORPHIC_TAG), | |
1156 *code, code->arguments_count())); | |
1157 GDBJIT(AddCode(GDBJITInterface::CALL_MEGAMORPHIC, *code)); | |
1158 return code; | |
1159 } | |
1160 | |
1161 | |
1162 Handle<Code> StubCompiler::CompileCallMiss(Code::Flags flags) { | |
1163 int argc = Code::ExtractArgumentsCountFromFlags(flags); | |
1164 Code::Kind kind = Code::ExtractKindFromFlags(flags); | |
1165 ExtraICState extra_state = Code::ExtractExtraICStateFromFlags(flags); | |
1166 if (kind == Code::CALL_IC) { | |
1167 CallIC::GenerateMiss(masm(), argc, extra_state); | |
1168 } else { | |
1169 KeyedCallIC::GenerateMiss(masm(), argc); | |
1170 } | |
1171 Handle<Code> code = GetCodeWithFlags(flags, "CompileCallMiss"); | |
1172 isolate()->counters()->call_megamorphic_stubs()->Increment(); | |
1173 PROFILE(isolate(), | |
1174 CodeCreateEvent(CALL_LOGGER_TAG(kind, CALL_MISS_TAG), | |
1175 *code, code->arguments_count())); | |
1176 GDBJIT(AddCode(GDBJITInterface::CALL_MISS, *code)); | |
1177 return code; | |
1178 } | |
1179 | |
1180 | |
1181 #ifdef ENABLE_DEBUGGER_SUPPORT | |
1182 Handle<Code> StubCompiler::CompileCallDebugBreak(Code::Flags flags) { | |
1183 Debug::GenerateCallICDebugBreak(masm()); | |
1184 Handle<Code> code = GetCodeWithFlags(flags, "CompileCallDebugBreak"); | |
1185 PROFILE(isolate(), | |
1186 CodeCreateEvent(CALL_LOGGER_TAG(Code::ExtractKindFromFlags(flags), | |
1187 CALL_DEBUG_BREAK_TAG), | |
1188 *code, code->arguments_count())); | |
1189 return code; | |
1190 } | |
1191 | |
1192 | |
1193 Handle<Code> StubCompiler::CompileCallDebugPrepareStepIn(Code::Flags flags) { | |
1194 // Use the same code for the the step in preparations as we do for the | |
1195 // miss case. | |
1196 int argc = Code::ExtractArgumentsCountFromFlags(flags); | |
1197 Code::Kind kind = Code::ExtractKindFromFlags(flags); | |
1198 if (kind == Code::CALL_IC) { | |
1199 // For the debugger extra ic state is irrelevant. | |
1200 CallIC::GenerateMiss(masm(), argc, kNoExtraICState); | |
1201 } else { | |
1202 KeyedCallIC::GenerateMiss(masm(), argc); | |
1203 } | |
1204 Handle<Code> code = GetCodeWithFlags(flags, "CompileCallDebugPrepareStepIn"); | |
1205 PROFILE(isolate(), | |
1206 CodeCreateEvent( | |
1207 CALL_LOGGER_TAG(kind, CALL_DEBUG_PREPARE_STEP_IN_TAG), | |
1208 *code, | |
1209 code->arguments_count())); | |
1210 return code; | |
1211 } | |
1212 #endif // ENABLE_DEBUGGER_SUPPORT | |
1213 | |
1214 #undef CALL_LOGGER_TAG | 747 #undef CALL_LOGGER_TAG |
1215 | 748 |
1216 | 749 |
1217 Handle<Code> StubCompiler::GetCodeWithFlags(Code::Flags flags, | 750 Handle<Code> StubCompiler::GetCodeWithFlags(Code::Flags flags, |
1218 const char* name) { | 751 const char* name) { |
1219 // Create code object in the heap. | 752 // Create code object in the heap. |
1220 CodeDesc desc; | 753 CodeDesc desc; |
1221 masm_.GetCode(&desc); | 754 masm_.GetCode(&desc); |
1222 Handle<Code> code = factory()->NewCode(desc, flags, masm_.CodeObject()); | 755 Handle<Code> code = factory()->NewCode(desc, flags, masm_.CodeObject()); |
1223 if (code->has_major_key()) { | 756 if (code->has_major_key()) { |
(...skipping 20 matching lines...) Expand all Loading... |
1244 holder->LocalLookupRealNamedProperty(*name, lookup); | 777 holder->LocalLookupRealNamedProperty(*name, lookup); |
1245 if (lookup->IsFound()) return; | 778 if (lookup->IsFound()) return; |
1246 if (holder->GetPrototype()->IsNull()) return; | 779 if (holder->GetPrototype()->IsNull()) return; |
1247 holder->GetPrototype()->Lookup(*name, lookup); | 780 holder->GetPrototype()->Lookup(*name, lookup); |
1248 } | 781 } |
1249 | 782 |
1250 | 783 |
1251 #define __ ACCESS_MASM(masm()) | 784 #define __ ACCESS_MASM(masm()) |
1252 | 785 |
1253 | 786 |
1254 void CallStubCompiler::HandlerFrontendFooter(Label* miss) { | |
1255 __ bind(miss); | |
1256 GenerateMissBranch(); | |
1257 } | |
1258 | |
1259 | |
1260 void CallStubCompiler::GenerateJumpFunctionIgnoreReceiver( | |
1261 Handle<JSFunction> function) { | |
1262 ParameterCount expected(function); | |
1263 __ InvokeFunction(function, expected, arguments(), | |
1264 JUMP_FUNCTION, NullCallWrapper()); | |
1265 } | |
1266 | |
1267 | |
1268 void CallStubCompiler::GenerateJumpFunction(Handle<Object> object, | |
1269 Handle<JSFunction> function) { | |
1270 PatchImplicitReceiver(object); | |
1271 GenerateJumpFunctionIgnoreReceiver(function); | |
1272 } | |
1273 | |
1274 | |
1275 void CallStubCompiler::GenerateJumpFunction(Handle<Object> object, | |
1276 Register actual_closure, | |
1277 Handle<JSFunction> function) { | |
1278 PatchImplicitReceiver(object); | |
1279 ParameterCount expected(function); | |
1280 __ InvokeFunction(actual_closure, expected, arguments(), | |
1281 JUMP_FUNCTION, NullCallWrapper()); | |
1282 } | |
1283 | |
1284 | |
1285 Handle<Code> CallStubCompiler::CompileCallConstant( | |
1286 Handle<Object> object, | |
1287 Handle<JSObject> holder, | |
1288 Handle<Name> name, | |
1289 CheckType check, | |
1290 Handle<JSFunction> function) { | |
1291 if (HasCustomCallGenerator(function)) { | |
1292 Handle<Code> code = CompileCustomCall(object, holder, | |
1293 Handle<Cell>::null(), | |
1294 function, Handle<String>::cast(name), | |
1295 Code::FAST); | |
1296 // A null handle means bail out to the regular compiler code below. | |
1297 if (!code.is_null()) return code; | |
1298 } | |
1299 | |
1300 Label miss; | |
1301 HandlerFrontendHeader(object, holder, name, check, &miss); | |
1302 GenerateJumpFunction(object, function); | |
1303 HandlerFrontendFooter(&miss); | |
1304 | |
1305 // Return the generated code. | |
1306 return GetCode(function); | |
1307 } | |
1308 | |
1309 | |
1310 Register LoadStubCompiler::HandlerFrontendHeader( | 787 Register LoadStubCompiler::HandlerFrontendHeader( |
1311 Handle<HeapType> type, | 788 Handle<HeapType> type, |
1312 Register object_reg, | 789 Register object_reg, |
1313 Handle<JSObject> holder, | 790 Handle<JSObject> holder, |
1314 Handle<Name> name, | 791 Handle<Name> name, |
1315 Label* miss) { | 792 Label* miss) { |
1316 PrototypeCheckType check_type = CHECK_ALL_MAPS; | 793 PrototypeCheckType check_type = CHECK_ALL_MAPS; |
1317 int function_index = -1; | 794 int function_index = -1; |
1318 if (type->Is(HeapType::String())) { | 795 if (type->Is(HeapType::String())) { |
1319 function_index = Context::STRING_FUNCTION_INDEX; | 796 function_index = Context::STRING_FUNCTION_INDEX; |
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1424 HandlerFrontendFooter(name, &miss); | 901 HandlerFrontendFooter(name, &miss); |
1425 } | 902 } |
1426 | 903 |
1427 | 904 |
1428 Handle<Code> LoadStubCompiler::CompileLoadField( | 905 Handle<Code> LoadStubCompiler::CompileLoadField( |
1429 Handle<HeapType> type, | 906 Handle<HeapType> type, |
1430 Handle<JSObject> holder, | 907 Handle<JSObject> holder, |
1431 Handle<Name> name, | 908 Handle<Name> name, |
1432 PropertyIndex field, | 909 PropertyIndex field, |
1433 Representation representation) { | 910 Representation representation) { |
1434 Label miss; | 911 Register reg = HandlerFrontend(type, receiver(), holder, name); |
1435 | |
1436 Register reg = HandlerFrontendHeader(type, receiver(), holder, name, &miss); | |
1437 | |
1438 GenerateLoadField(reg, holder, field, representation); | 912 GenerateLoadField(reg, holder, field, representation); |
1439 | 913 |
1440 __ bind(&miss); | |
1441 TailCallBuiltin(masm(), MissBuiltin(kind())); | |
1442 | |
1443 // Return the generated code. | 914 // Return the generated code. |
1444 return GetCode(kind(), Code::FAST, name); | 915 return GetCode(kind(), Code::FAST, name); |
1445 } | 916 } |
1446 | 917 |
1447 | 918 |
1448 Handle<Code> LoadStubCompiler::CompileLoadConstant( | 919 Handle<Code> LoadStubCompiler::CompileLoadConstant( |
1449 Handle<HeapType> type, | 920 Handle<HeapType> type, |
1450 Handle<JSObject> holder, | 921 Handle<JSObject> holder, |
1451 Handle<Name> name, | 922 Handle<Name> name, |
1452 Handle<Object> value) { | 923 Handle<Object> value) { |
(...skipping 405 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1858 return code; | 1329 return code; |
1859 } | 1330 } |
1860 | 1331 |
1861 | 1332 |
1862 void KeyedStoreStubCompiler::GenerateStoreDictionaryElement( | 1333 void KeyedStoreStubCompiler::GenerateStoreDictionaryElement( |
1863 MacroAssembler* masm) { | 1334 MacroAssembler* masm) { |
1864 KeyedStoreIC::GenerateSlow(masm); | 1335 KeyedStoreIC::GenerateSlow(masm); |
1865 } | 1336 } |
1866 | 1337 |
1867 | 1338 |
1868 CallStubCompiler::CallStubCompiler(Isolate* isolate, | |
1869 int argc, | |
1870 Code::Kind kind, | |
1871 ExtraICState extra_state, | |
1872 InlineCacheHolderFlag cache_holder) | |
1873 : StubCompiler(isolate, extra_state), | |
1874 arguments_(argc), | |
1875 kind_(kind), | |
1876 cache_holder_(cache_holder) { | |
1877 } | |
1878 | |
1879 | |
1880 bool CallStubCompiler::HasCustomCallGenerator(Handle<JSFunction> function) { | |
1881 CallOptimization optimization(function); | |
1882 return optimization.is_simple_api_call(); | |
1883 } | |
1884 | |
1885 | |
1886 Handle<Code> CallStubCompiler::CompileCustomCall( | |
1887 Handle<Object> object, | |
1888 Handle<JSObject> holder, | |
1889 Handle<Cell> cell, | |
1890 Handle<JSFunction> function, | |
1891 Handle<String> fname, | |
1892 Code::StubType type) { | |
1893 ASSERT(HasCustomCallGenerator(function)); | |
1894 CallOptimization optimization(function); | |
1895 ASSERT(optimization.is_simple_api_call()); | |
1896 return CompileFastApiCall(optimization, | |
1897 object, | |
1898 holder, | |
1899 cell, | |
1900 function, | |
1901 fname); | |
1902 } | |
1903 | |
1904 | |
1905 Handle<Code> CallStubCompiler::GetCode(Code::StubType type, | |
1906 Handle<Name> name) { | |
1907 int argc = arguments_.immediate(); | |
1908 Code::Flags flags = Code::ComputeMonomorphicFlags( | |
1909 kind_, extra_state(), cache_holder_, type, argc); | |
1910 return GetCodeWithFlags(flags, name); | |
1911 } | |
1912 | |
1913 | |
1914 Handle<Code> CallStubCompiler::GetCode(Handle<JSFunction> function) { | |
1915 Handle<String> function_name; | |
1916 if (function->shared()->name()->IsString()) { | |
1917 function_name = Handle<String>(String::cast(function->shared()->name())); | |
1918 } | |
1919 return GetCode(Code::FAST, function_name); | |
1920 } | |
1921 | |
1922 | |
1923 CallOptimization::CallOptimization(LookupResult* lookup) { | 1339 CallOptimization::CallOptimization(LookupResult* lookup) { |
1924 if (lookup->IsFound() && | 1340 if (lookup->IsFound() && |
1925 lookup->IsCacheable() && | 1341 lookup->IsCacheable() && |
1926 lookup->IsConstantFunction()) { | 1342 lookup->IsConstantFunction()) { |
1927 // We only optimize constant function calls. | 1343 // We only optimize constant function calls. |
1928 Initialize(Handle<JSFunction>(lookup->GetConstantFunction())); | 1344 Initialize(Handle<JSFunction>(lookup->GetConstantFunction())); |
1929 } else { | 1345 } else { |
1930 Initialize(Handle<JSFunction>::null()); | 1346 Initialize(Handle<JSFunction>::null()); |
1931 } | 1347 } |
1932 } | 1348 } |
1933 | 1349 |
1934 | 1350 |
1935 CallOptimization::CallOptimization(Handle<JSFunction> function) { | 1351 CallOptimization::CallOptimization(Handle<JSFunction> function) { |
1936 Initialize(function); | 1352 Initialize(function); |
1937 } | 1353 } |
1938 | 1354 |
1939 | 1355 |
1940 Handle<Map> CallOptimization::LookupHolderOfExpectedType( | 1356 Handle<JSObject> CallOptimization::LookupHolderOfExpectedType( |
1941 Handle<JSObject> receiver, | 1357 Handle<Map> object_map, |
1942 Handle<JSObject> object, | |
1943 Handle<JSObject> holder, | |
1944 HolderLookup* holder_lookup) const { | 1358 HolderLookup* holder_lookup) const { |
1945 ASSERT(is_simple_api_call()); | 1359 ASSERT(is_simple_api_call()); |
1946 ASSERT_EQ(kHolderNotFound, *holder_lookup); | 1360 ASSERT_EQ(kHolderNotFound, *holder_lookup); |
1947 *holder_lookup = kHolderIsReceiver; | 1361 if (!object_map->IsJSObjectMap()) { |
1948 Handle<Map> map_to_holder; | 1362 *holder_lookup = kHolderNotFound; |
1949 if (expected_receiver_type_.is_null()) { | 1363 return Handle<JSObject>::null(); |
1950 // no expected type, load from receiver. | |
1951 return map_to_holder; | |
1952 } | 1364 } |
1953 // walk down the prototype chain to the object | 1365 if (expected_receiver_type_.is_null() || |
1954 while (!receiver.is_identical_to(object)) { | 1366 expected_receiver_type_->IsTemplateFor(*object_map)) { |
1955 *holder_lookup = kHolderIsPrototypeOfMap; | 1367 *holder_lookup = kHolderIsReceiver; |
1956 map_to_holder = Handle<Map>(receiver->map()); | 1368 return Handle<JSObject>::null(); |
1957 receiver = Handle<JSObject>(JSObject::cast(map_to_holder->prototype())); | |
1958 } | 1369 } |
1959 // start looking for the holder | 1370 while (true) { |
1960 while (!object.is_identical_to(holder)) { | 1371 if (!object_map->prototype()->IsJSObject()) break; |
1961 Handle<Map> object_map(object->map()); | 1372 Handle<JSObject> prototype(JSObject::cast(object_map->prototype())); |
| 1373 if (!prototype->map()->is_hidden_prototype()) break; |
| 1374 object_map = handle(prototype->map()); |
1962 if (expected_receiver_type_->IsTemplateFor(*object_map)) { | 1375 if (expected_receiver_type_->IsTemplateFor(*object_map)) { |
1963 return map_to_holder; | 1376 *holder_lookup = kHolderFound; |
| 1377 return prototype; |
1964 } | 1378 } |
1965 if (!object_map->is_hidden_prototype()) { | |
1966 *holder_lookup = kHolderNotFound; | |
1967 return Handle<Map>::null(); | |
1968 } | |
1969 *holder_lookup = kHolderIsPrototypeOfMap; | |
1970 map_to_holder = object_map; | |
1971 object = Handle<JSObject>(JSObject::cast(object_map->prototype())); | |
1972 } | |
1973 if (expected_receiver_type_->IsTemplateFor(holder->map())) { | |
1974 return map_to_holder; | |
1975 } | 1379 } |
1976 *holder_lookup = kHolderNotFound; | 1380 *holder_lookup = kHolderNotFound; |
1977 return Handle<Map>::null(); | 1381 return Handle<JSObject>::null(); |
1978 } | 1382 } |
1979 | 1383 |
1980 | 1384 |
1981 void CallOptimization::Initialize(Handle<JSFunction> function) { | 1385 void CallOptimization::Initialize(Handle<JSFunction> function) { |
1982 constant_function_ = Handle<JSFunction>::null(); | 1386 constant_function_ = Handle<JSFunction>::null(); |
1983 is_simple_api_call_ = false; | 1387 is_simple_api_call_ = false; |
1984 expected_receiver_type_ = Handle<FunctionTemplateInfo>::null(); | 1388 expected_receiver_type_ = Handle<FunctionTemplateInfo>::null(); |
1985 api_call_info_ = Handle<CallHandlerInfo>::null(); | 1389 api_call_info_ = Handle<CallHandlerInfo>::null(); |
1986 | 1390 |
1987 if (function.is_null() || !function->is_compiled()) return; | 1391 if (function.is_null() || !function->is_compiled()) return; |
(...skipping 23 matching lines...) Expand all Loading... |
2011 Handle<FunctionTemplateInfo>( | 1415 Handle<FunctionTemplateInfo>( |
2012 FunctionTemplateInfo::cast(signature->receiver())); | 1416 FunctionTemplateInfo::cast(signature->receiver())); |
2013 } | 1417 } |
2014 } | 1418 } |
2015 | 1419 |
2016 is_simple_api_call_ = true; | 1420 is_simple_api_call_ = true; |
2017 } | 1421 } |
2018 | 1422 |
2019 | 1423 |
2020 } } // namespace v8::internal | 1424 } } // namespace v8::internal |
OLD | NEW |