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 406 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
417 // Don't clear debug break inline cache as it will remove the break point. | 417 // Don't clear debug break inline cache as it will remove the break point. |
418 if (target->is_debug_stub()) return; | 418 if (target->is_debug_stub()) return; |
419 | 419 |
420 switch (target->kind()) { | 420 switch (target->kind()) { |
421 case Code::LOAD_IC: return LoadIC::Clear(isolate, address, target); | 421 case Code::LOAD_IC: return LoadIC::Clear(isolate, address, target); |
422 case Code::KEYED_LOAD_IC: | 422 case Code::KEYED_LOAD_IC: |
423 return KeyedLoadIC::Clear(isolate, address, target); | 423 return KeyedLoadIC::Clear(isolate, address, target); |
424 case Code::STORE_IC: return StoreIC::Clear(isolate, address, target); | 424 case Code::STORE_IC: return StoreIC::Clear(isolate, address, target); |
425 case Code::KEYED_STORE_IC: | 425 case Code::KEYED_STORE_IC: |
426 return KeyedStoreIC::Clear(isolate, address, target); | 426 return KeyedStoreIC::Clear(isolate, address, target); |
427 case Code::CALL_IC: return CallIC::Clear(address, target); | |
428 case Code::KEYED_CALL_IC: return KeyedCallIC::Clear(address, target); | |
429 case Code::COMPARE_IC: return CompareIC::Clear(isolate, address, target); | 427 case Code::COMPARE_IC: return CompareIC::Clear(isolate, address, target); |
430 case Code::COMPARE_NIL_IC: return CompareNilIC::Clear(address, target); | 428 case Code::COMPARE_NIL_IC: return CompareNilIC::Clear(address, target); |
431 case Code::BINARY_OP_IC: | 429 case Code::BINARY_OP_IC: |
432 case Code::TO_BOOLEAN_IC: | 430 case Code::TO_BOOLEAN_IC: |
433 // Clearing these is tricky and does not | 431 // Clearing these is tricky and does not |
434 // make any performance difference. | 432 // make any performance difference. |
435 return; | 433 return; |
436 default: UNREACHABLE(); | 434 default: UNREACHABLE(); |
437 } | 435 } |
438 } | 436 } |
439 | 437 |
440 | 438 |
441 void CallICBase::Clear(Address address, Code* target) { | |
442 if (IsCleared(target)) return; | |
443 Code* code = target->GetIsolate()->stub_cache()->FindCallInitialize( | |
444 target->arguments_count(), target->kind()); | |
445 SetTargetAtAddress(address, code); | |
446 } | |
447 | |
448 | |
449 void KeyedLoadIC::Clear(Isolate* isolate, Address address, Code* target) { | 439 void KeyedLoadIC::Clear(Isolate* isolate, Address address, Code* target) { |
450 if (IsCleared(target)) return; | 440 if (IsCleared(target)) return; |
451 // Make sure to also clear the map used in inline fast cases. If we | 441 // Make sure to also clear the map used in inline fast cases. If we |
452 // do not clear these maps, cached code can keep objects alive | 442 // do not clear these maps, cached code can keep objects alive |
453 // through the embedded maps. | 443 // through the embedded maps. |
454 SetTargetAtAddress(address, *pre_monomorphic_stub(isolate)); | 444 SetTargetAtAddress(address, *pre_monomorphic_stub(isolate)); |
455 } | 445 } |
456 | 446 |
457 | 447 |
458 void LoadIC::Clear(Isolate* isolate, Address address, Code* target) { | 448 void LoadIC::Clear(Isolate* isolate, Address address, Code* target) { |
(...skipping 26 matching lines...) Expand all Loading... |
485 Token::Value op; | 475 Token::Value op; |
486 ICCompareStub::DecodeMinorKey(target->stub_info(), NULL, NULL, | 476 ICCompareStub::DecodeMinorKey(target->stub_info(), NULL, NULL, |
487 &handler_state, &op); | 477 &handler_state, &op); |
488 // Only clear CompareICs that can retain objects. | 478 // Only clear CompareICs that can retain objects. |
489 if (handler_state != KNOWN_OBJECT) return; | 479 if (handler_state != KNOWN_OBJECT) return; |
490 SetTargetAtAddress(address, GetRawUninitialized(isolate, op)); | 480 SetTargetAtAddress(address, GetRawUninitialized(isolate, op)); |
491 PatchInlinedSmiCode(address, DISABLE_INLINED_SMI_CHECK); | 481 PatchInlinedSmiCode(address, DISABLE_INLINED_SMI_CHECK); |
492 } | 482 } |
493 | 483 |
494 | 484 |
495 Handle<Object> CallICBase::TryCallAsFunction(Handle<Object> object) { | |
496 Handle<Object> delegate = Execution::GetFunctionDelegate(isolate(), object); | |
497 | |
498 if (delegate->IsJSFunction() && !object->IsJSFunctionProxy()) { | |
499 // Patch the receiver and use the delegate as the function to | |
500 // invoke. This is used for invoking objects as if they were functions. | |
501 const int argc = target()->arguments_count(); | |
502 StackFrameLocator locator(isolate()); | |
503 JavaScriptFrame* frame = locator.FindJavaScriptFrame(0); | |
504 int index = frame->ComputeExpressionsCount() - (argc + 1); | |
505 frame->SetExpression(index, *object); | |
506 } | |
507 | |
508 return delegate; | |
509 } | |
510 | |
511 | |
512 void CallICBase::ReceiverToObjectIfRequired(Handle<Object> callee, | |
513 Handle<Object> object) { | |
514 while (callee->IsJSFunctionProxy()) { | |
515 callee = Handle<Object>(JSFunctionProxy::cast(*callee)->call_trap(), | |
516 isolate()); | |
517 } | |
518 | |
519 if (callee->IsJSFunction()) { | |
520 Handle<JSFunction> function = Handle<JSFunction>::cast(callee); | |
521 if (!function->shared()->is_classic_mode() || function->IsBuiltin()) { | |
522 // Do not wrap receiver for strict mode functions or for builtins. | |
523 return; | |
524 } | |
525 } | |
526 | |
527 // And only wrap string, number or boolean. | |
528 if (object->IsString() || object->IsNumber() || object->IsBoolean()) { | |
529 // Change the receiver to the result of calling ToObject on it. | |
530 const int argc = this->target()->arguments_count(); | |
531 StackFrameLocator locator(isolate()); | |
532 JavaScriptFrame* frame = locator.FindJavaScriptFrame(0); | |
533 int index = frame->ComputeExpressionsCount() - (argc + 1); | |
534 frame->SetExpression(index, *isolate()->factory()->ToObject(object)); | |
535 } | |
536 } | |
537 | |
538 | |
539 static bool MigrateDeprecated(Handle<Object> object) { | 485 static bool MigrateDeprecated(Handle<Object> object) { |
540 if (!object->IsJSObject()) return false; | 486 if (!object->IsJSObject()) return false; |
541 Handle<JSObject> receiver = Handle<JSObject>::cast(object); | 487 Handle<JSObject> receiver = Handle<JSObject>::cast(object); |
542 if (!receiver->map()->is_deprecated()) return false; | 488 if (!receiver->map()->is_deprecated()) return false; |
543 JSObject::MigrateInstance(Handle<JSObject>::cast(object)); | 489 JSObject::MigrateInstance(Handle<JSObject>::cast(object)); |
544 return true; | 490 return true; |
545 } | 491 } |
546 | 492 |
547 | 493 |
548 MaybeObject* CallICBase::LoadFunction(Handle<Object> object, | |
549 Handle<String> name) { | |
550 bool use_ic = MigrateDeprecated(object) ? false : FLAG_use_ic; | |
551 | |
552 // If the object is undefined or null it's illegal to try to get any | |
553 // of its properties; throw a TypeError in that case. | |
554 if (object->IsUndefined() || object->IsNull()) { | |
555 return TypeError("non_object_property_call", object, name); | |
556 } | |
557 | |
558 // Check if the name is trivially convertible to an index and get | |
559 // the element if so. | |
560 uint32_t index; | |
561 if (name->AsArrayIndex(&index)) { | |
562 Handle<Object> result = Object::GetElement(isolate(), object, index); | |
563 RETURN_IF_EMPTY_HANDLE(isolate(), result); | |
564 if (result->IsJSFunction()) return *result; | |
565 | |
566 // Try to find a suitable function delegate for the object at hand. | |
567 result = TryCallAsFunction(result); | |
568 if (result->IsJSFunction()) return *result; | |
569 | |
570 // Otherwise, it will fail in the lookup step. | |
571 } | |
572 | |
573 // Lookup the property in the object. | |
574 LookupResult lookup(isolate()); | |
575 LookupForRead(object, name, &lookup); | |
576 | |
577 if (!lookup.IsFound()) { | |
578 // If the object does not have the requested property, check which | |
579 // exception we need to throw. | |
580 return object->IsGlobalObject() | |
581 ? ReferenceError("not_defined", name) | |
582 : TypeError("undefined_method", object, name); | |
583 } | |
584 | |
585 // Lookup is valid: Update inline cache and stub cache. | |
586 if (use_ic) UpdateCaches(&lookup, object, name); | |
587 | |
588 // Get the property. | |
589 PropertyAttributes attr; | |
590 Handle<Object> result = | |
591 Object::GetProperty(object, object, &lookup, name, &attr); | |
592 RETURN_IF_EMPTY_HANDLE(isolate(), result); | |
593 | |
594 if (lookup.IsInterceptor() && attr == ABSENT) { | |
595 // If the object does not have the requested property, check which | |
596 // exception we need to throw. | |
597 return object->IsGlobalObject() | |
598 ? ReferenceError("not_defined", name) | |
599 : TypeError("undefined_method", object, name); | |
600 } | |
601 | |
602 ASSERT(!result->IsTheHole()); | |
603 | |
604 // Make receiver an object if the callee requires it. Strict mode or builtin | |
605 // functions do not wrap the receiver, non-strict functions and objects | |
606 // called as functions do. | |
607 ReceiverToObjectIfRequired(result, object); | |
608 | |
609 if (result->IsJSFunction()) { | |
610 Handle<JSFunction> function = Handle<JSFunction>::cast(result); | |
611 #ifdef ENABLE_DEBUGGER_SUPPORT | |
612 // Handle stepping into a function if step into is active. | |
613 Debug* debug = isolate()->debug(); | |
614 if (debug->StepInActive()) { | |
615 // Protect the result in a handle as the debugger can allocate and might | |
616 // cause GC. | |
617 debug->HandleStepIn(function, object, fp(), false); | |
618 } | |
619 #endif | |
620 return *function; | |
621 } | |
622 | |
623 // Try to find a suitable function delegate for the object at hand. | |
624 result = TryCallAsFunction(result); | |
625 if (result->IsJSFunction()) return *result; | |
626 | |
627 return TypeError("property_not_function", object, name); | |
628 } | |
629 | |
630 | |
631 Handle<Code> CallICBase::ComputeMonomorphicStub(LookupResult* lookup, | |
632 Handle<Object> object, | |
633 Handle<String> name) { | |
634 int argc = target()->arguments_count(); | |
635 Handle<JSObject> holder(lookup->holder(), isolate()); | |
636 switch (lookup->type()) { | |
637 case FIELD: { | |
638 PropertyIndex index = lookup->GetFieldIndex(); | |
639 return isolate()->stub_cache()->ComputeCallField( | |
640 argc, kind_, extra_ic_state(), name, object, holder, index); | |
641 } | |
642 case CONSTANT: { | |
643 if (!lookup->IsConstantFunction()) return Handle<Code>::null(); | |
644 // Get the constant function and compute the code stub for this | |
645 // call; used for rewriting to monomorphic state and making sure | |
646 // that the code stub is in the stub cache. | |
647 Handle<JSFunction> function(lookup->GetConstantFunction(), isolate()); | |
648 return isolate()->stub_cache()->ComputeCallConstant( | |
649 argc, kind_, extra_ic_state(), name, object, holder, function); | |
650 } | |
651 case NORMAL: { | |
652 // If we return a null handle, the IC will not be patched. | |
653 if (!object->IsJSObject()) return Handle<Code>::null(); | |
654 Handle<JSObject> receiver = Handle<JSObject>::cast(object); | |
655 | |
656 if (holder->IsGlobalObject()) { | |
657 Handle<GlobalObject> global = Handle<GlobalObject>::cast(holder); | |
658 Handle<PropertyCell> cell( | |
659 global->GetPropertyCell(lookup), isolate()); | |
660 if (!cell->value()->IsJSFunction()) return Handle<Code>::null(); | |
661 Handle<JSFunction> function(JSFunction::cast(cell->value())); | |
662 return isolate()->stub_cache()->ComputeCallGlobal( | |
663 argc, kind_, extra_ic_state(), name, | |
664 receiver, global, cell, function); | |
665 } else { | |
666 // There is only one shared stub for calling normalized | |
667 // properties. It does not traverse the prototype chain, so the | |
668 // property must be found in the receiver for the stub to be | |
669 // applicable. | |
670 if (!holder.is_identical_to(receiver)) return Handle<Code>::null(); | |
671 return isolate()->stub_cache()->ComputeCallNormal( | |
672 argc, kind_, extra_ic_state()); | |
673 } | |
674 break; | |
675 } | |
676 case INTERCEPTOR: | |
677 ASSERT(HasInterceptorGetter(*holder)); | |
678 return isolate()->stub_cache()->ComputeCallInterceptor( | |
679 argc, kind_, extra_ic_state(), name, object, holder); | |
680 default: | |
681 return Handle<Code>::null(); | |
682 } | |
683 } | |
684 | |
685 | |
686 Handle<Code> CallICBase::megamorphic_stub() { | |
687 return isolate()->stub_cache()->ComputeCallMegamorphic( | |
688 target()->arguments_count(), kind_, extra_ic_state()); | |
689 } | |
690 | |
691 | |
692 Handle<Code> CallICBase::pre_monomorphic_stub() { | |
693 return isolate()->stub_cache()->ComputeCallPreMonomorphic( | |
694 target()->arguments_count(), kind_, extra_ic_state()); | |
695 } | |
696 | |
697 | |
698 void CallICBase::UpdateCaches(LookupResult* lookup, | |
699 Handle<Object> object, | |
700 Handle<String> name) { | |
701 // Bail out if we didn't find a result. | |
702 if (!lookup->IsProperty() || !lookup->IsCacheable()) return; | |
703 | |
704 if (state() == UNINITIALIZED) { | |
705 set_target(*pre_monomorphic_stub()); | |
706 TRACE_IC("CallIC", name); | |
707 return; | |
708 } | |
709 | |
710 Handle<Code> code = ComputeMonomorphicStub(lookup, object, name); | |
711 // If there's no appropriate stub we simply avoid updating the caches. | |
712 // TODO(verwaest): Install a slow fallback in this case to avoid not learning, | |
713 // and deopting Crankshaft code. | |
714 if (code.is_null()) return; | |
715 | |
716 Handle<JSObject> cache_object = object->IsJSObject() | |
717 ? Handle<JSObject>::cast(object) | |
718 : Handle<JSObject>(JSObject::cast(object->GetPrototype(isolate())), | |
719 isolate()); | |
720 | |
721 PatchCache(CurrentTypeOf(cache_object, isolate()), name, code); | |
722 TRACE_IC("CallIC", name); | |
723 } | |
724 | |
725 | |
726 MaybeObject* KeyedCallIC::LoadFunction(Handle<Object> object, | |
727 Handle<Object> key) { | |
728 if (key->IsInternalizedString()) { | |
729 return CallICBase::LoadFunction(object, Handle<String>::cast(key)); | |
730 } | |
731 | |
732 if (object->IsUndefined() || object->IsNull()) { | |
733 return TypeError("non_object_property_call", object, key); | |
734 } | |
735 | |
736 bool use_ic = MigrateDeprecated(object) | |
737 ? false : FLAG_use_ic && !object->IsAccessCheckNeeded(); | |
738 | |
739 if (use_ic && state() != MEGAMORPHIC) { | |
740 ASSERT(!object->IsJSGlobalProxy()); | |
741 int argc = target()->arguments_count(); | |
742 Handle<Code> stub; | |
743 | |
744 // Use the KeyedArrayCallStub if the call is of the form array[smi](...), | |
745 // where array is an instance of one of the initial array maps (without | |
746 // extra named properties). | |
747 // TODO(verwaest): Also support keyed calls on instances of other maps. | |
748 if (object->IsJSArray() && key->IsSmi()) { | |
749 Handle<JSArray> array = Handle<JSArray>::cast(object); | |
750 ElementsKind kind = array->map()->elements_kind(); | |
751 if (IsFastObjectElementsKind(kind) && | |
752 array->map() == isolate()->get_initial_js_array_map(kind)) { | |
753 KeyedArrayCallStub stub_gen(IsHoleyElementsKind(kind), argc); | |
754 stub = stub_gen.GetCode(isolate()); | |
755 } | |
756 } | |
757 | |
758 if (stub.is_null()) { | |
759 stub = isolate()->stub_cache()->ComputeCallMegamorphic( | |
760 argc, Code::KEYED_CALL_IC, kNoExtraICState); | |
761 if (object->IsJSObject()) { | |
762 Handle<JSObject> receiver = Handle<JSObject>::cast(object); | |
763 if (receiver->elements()->map() == | |
764 isolate()->heap()->non_strict_arguments_elements_map()) { | |
765 stub = isolate()->stub_cache()->ComputeCallArguments(argc); | |
766 } | |
767 } | |
768 ASSERT(!stub.is_null()); | |
769 } | |
770 set_target(*stub); | |
771 TRACE_IC("CallIC", key); | |
772 } | |
773 | |
774 Handle<Object> result = GetProperty(isolate(), object, key); | |
775 RETURN_IF_EMPTY_HANDLE(isolate(), result); | |
776 | |
777 // Make receiver an object if the callee requires it. Strict mode or builtin | |
778 // functions do not wrap the receiver, non-strict functions and objects | |
779 // called as functions do. | |
780 ReceiverToObjectIfRequired(result, object); | |
781 if (result->IsJSFunction()) return *result; | |
782 | |
783 result = TryCallAsFunction(result); | |
784 if (result->IsJSFunction()) return *result; | |
785 | |
786 return TypeError("property_not_function", object, key); | |
787 } | |
788 | |
789 | |
790 MaybeObject* LoadIC::Load(Handle<Object> object, | 494 MaybeObject* LoadIC::Load(Handle<Object> object, |
791 Handle<String> name) { | 495 Handle<String> name) { |
792 // If the object is undefined or null it's illegal to try to get any | 496 // If the object is undefined or null it's illegal to try to get any |
793 // of its properties; throw a TypeError in that case. | 497 // of its properties; throw a TypeError in that case. |
794 if (object->IsUndefined() || object->IsNull()) { | 498 if (object->IsUndefined() || object->IsNull()) { |
795 return TypeError("non_object_property_load", object, name); | 499 return TypeError("non_object_property_load", object, name); |
796 } | 500 } |
797 | 501 |
798 if (FLAG_use_ic) { | 502 if (FLAG_use_ic) { |
799 // Use specialized code for getting the length of strings and | 503 // Use specialized code for getting the length of strings and |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
873 // Get the property. | 577 // Get the property. |
874 Handle<Object> result = | 578 Handle<Object> result = |
875 Object::GetProperty(object, object, &lookup, name, &attr); | 579 Object::GetProperty(object, object, &lookup, name, &attr); |
876 RETURN_IF_EMPTY_HANDLE(isolate(), result); | 580 RETURN_IF_EMPTY_HANDLE(isolate(), result); |
877 // If the property is not present, check if we need to throw an | 581 // If the property is not present, check if we need to throw an |
878 // exception. | 582 // exception. |
879 if ((lookup.IsInterceptor() || lookup.IsHandler()) && | 583 if ((lookup.IsInterceptor() || lookup.IsHandler()) && |
880 attr == ABSENT && IsUndeclaredGlobal(object)) { | 584 attr == ABSENT && IsUndeclaredGlobal(object)) { |
881 return ReferenceError("not_defined", name); | 585 return ReferenceError("not_defined", name); |
882 } | 586 } |
| 587 |
883 return *result; | 588 return *result; |
884 } | 589 } |
885 | 590 |
886 | 591 |
887 static bool AddOneReceiverMapIfMissing(MapHandleList* receiver_maps, | 592 static bool AddOneReceiverMapIfMissing(MapHandleList* receiver_maps, |
888 Handle<Map> new_receiver_map) { | 593 Handle<Map> new_receiver_map) { |
889 ASSERT(!new_receiver_map.is_null()); | 594 ASSERT(!new_receiver_map.is_null()); |
890 for (int current = 0; current < receiver_maps->length(); ++current) { | 595 for (int current = 0; current < receiver_maps->length(); ++current) { |
891 if (!receiver_maps->at(current).is_null() && | 596 if (!receiver_maps->at(current).is_null() && |
892 receiver_maps->at(current).is_identical_to(new_receiver_map)) { | 597 receiver_maps->at(current).is_identical_to(new_receiver_map)) { |
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1020 Handle<Code> code) { | 725 Handle<Code> code) { |
1021 switch (state()) { | 726 switch (state()) { |
1022 case UNINITIALIZED: | 727 case UNINITIALIZED: |
1023 case PREMONOMORPHIC: | 728 case PREMONOMORPHIC: |
1024 case MONOMORPHIC_PROTOTYPE_FAILURE: | 729 case MONOMORPHIC_PROTOTYPE_FAILURE: |
1025 UpdateMonomorphicIC(type, code, name); | 730 UpdateMonomorphicIC(type, code, name); |
1026 break; | 731 break; |
1027 case MONOMORPHIC: { | 732 case MONOMORPHIC: { |
1028 // For now, call stubs are allowed to rewrite to the same stub. This | 733 // For now, call stubs are allowed to rewrite to the same stub. This |
1029 // happens e.g., when the field does not contain a function. | 734 // happens e.g., when the field does not contain a function. |
1030 ASSERT(target()->is_call_stub() || | 735 ASSERT(!target().is_identical_to(code)); |
1031 target()->is_keyed_call_stub() || | |
1032 !target().is_identical_to(code)); | |
1033 Code* old_handler = target()->FindFirstHandler(); | 736 Code* old_handler = target()->FindFirstHandler(); |
1034 if (old_handler == *code && IsTransitionOfMonomorphicTarget(type)) { | 737 if (old_handler == *code && IsTransitionOfMonomorphicTarget(type)) { |
1035 UpdateMonomorphicIC(type, code, name); | 738 UpdateMonomorphicIC(type, code, name); |
1036 break; | 739 break; |
1037 } | 740 } |
1038 // Fall through. | 741 // Fall through. |
1039 } | 742 } |
1040 case POLYMORPHIC: | 743 case POLYMORPHIC: |
1041 if (!target()->is_keyed_stub()) { | 744 if (!target()->is_keyed_stub()) { |
1042 if (UpdatePolymorphicIC(type, name, code)) break; | 745 if (UpdatePolymorphicIC(type, name, code)) break; |
1043 CopyICToMegamorphicCache(name); | 746 CopyICToMegamorphicCache(name); |
1044 } | 747 } |
1045 set_target(*megamorphic_stub()); | 748 set_target(*megamorphic_stub()); |
1046 // Fall through. | 749 // Fall through. |
1047 case MEGAMORPHIC: | 750 case MEGAMORPHIC: |
1048 UpdateMegamorphicCache(*type, *name, *code); | 751 UpdateMegamorphicCache(*type, *name, *code); |
1049 break; | 752 break; |
1050 case DEBUG_STUB: | 753 case DEBUG_STUB: |
1051 break; | 754 break; |
1052 case GENERIC: | 755 case GENERIC: |
1053 UNREACHABLE(); | 756 UNREACHABLE(); |
1054 break; | 757 break; |
1055 } | 758 } |
1056 } | 759 } |
1057 | 760 |
1058 | 761 |
1059 Handle<Code> LoadIC::initialize_stub(Isolate* isolate, ContextualMode mode) { | 762 Handle<Code> LoadIC::initialize_stub(Isolate* isolate, |
1060 Handle<Code> ic = isolate->stub_cache()->ComputeLoad( | 763 ExtraICState extra_state) { |
1061 UNINITIALIZED, ComputeExtraICState(mode)); | 764 return isolate->stub_cache()->ComputeLoad(UNINITIALIZED, extra_state); |
1062 return ic; | |
1063 } | 765 } |
1064 | 766 |
1065 | 767 |
1066 Handle<Code> LoadIC::pre_monomorphic_stub(Isolate* isolate, | 768 Handle<Code> LoadIC::pre_monomorphic_stub(Isolate* isolate, |
1067 ContextualMode mode) { | 769 ExtraICState extra_state) { |
1068 return isolate->stub_cache()->ComputeLoad( | 770 return isolate->stub_cache()->ComputeLoad(PREMONOMORPHIC, extra_state); |
1069 PREMONOMORPHIC, ComputeExtraICState(mode)); | |
1070 } | 771 } |
1071 | 772 |
1072 | 773 |
1073 Handle<Code> LoadIC::megamorphic_stub() { | 774 Handle<Code> LoadIC::megamorphic_stub() { |
1074 return isolate()->stub_cache()->ComputeLoad( | 775 return isolate()->stub_cache()->ComputeLoad(MEGAMORPHIC, extra_ic_state()); |
1075 MEGAMORPHIC, extra_ic_state()); | |
1076 } | 776 } |
1077 | 777 |
1078 | 778 |
1079 Handle<Code> LoadIC::SimpleFieldLoad(int offset, | 779 Handle<Code> LoadIC::SimpleFieldLoad(int offset, |
1080 bool inobject, | 780 bool inobject, |
1081 Representation representation) { | 781 Representation representation) { |
1082 if (kind() == Code::LOAD_IC) { | 782 if (kind() == Code::LOAD_IC) { |
1083 LoadFieldStub stub(inobject, offset, representation); | 783 LoadFieldStub stub(inobject, offset, representation); |
1084 return stub.GetCode(isolate()); | 784 return stub.GetCode(isolate()); |
1085 } else { | 785 } else { |
(...skipping 932 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2018 | 1718 |
2019 | 1719 |
2020 #undef TRACE_IC | 1720 #undef TRACE_IC |
2021 | 1721 |
2022 | 1722 |
2023 // ---------------------------------------------------------------------------- | 1723 // ---------------------------------------------------------------------------- |
2024 // Static IC stub generators. | 1724 // Static IC stub generators. |
2025 // | 1725 // |
2026 | 1726 |
2027 // Used from ic-<arch>.cc. | 1727 // Used from ic-<arch>.cc. |
2028 RUNTIME_FUNCTION(MaybeObject*, CallIC_Miss) { | |
2029 HandleScope scope(isolate); | |
2030 ASSERT(args.length() == 2); | |
2031 CallIC ic(isolate); | |
2032 Handle<Object> receiver = args.at<Object>(0); | |
2033 Handle<String> key = args.at<String>(1); | |
2034 ic.UpdateState(receiver, key); | |
2035 MaybeObject* maybe_result = ic.LoadFunction(receiver, key); | |
2036 JSFunction* raw_function; | |
2037 if (!maybe_result->To(&raw_function)) return maybe_result; | |
2038 | |
2039 // The first time the inline cache is updated may be the first time the | |
2040 // function it references gets called. If the function is lazily compiled | |
2041 // then the first call will trigger a compilation. We check for this case | |
2042 // and we do the compilation immediately, instead of waiting for the stub | |
2043 // currently attached to the JSFunction object to trigger compilation. | |
2044 if (raw_function->is_compiled()) return raw_function; | |
2045 | |
2046 Handle<JSFunction> function(raw_function); | |
2047 Compiler::EnsureCompiled(function, CLEAR_EXCEPTION); | |
2048 return *function; | |
2049 } | |
2050 | |
2051 | |
2052 // Used from ic-<arch>.cc. | |
2053 RUNTIME_FUNCTION(MaybeObject*, KeyedCallIC_Miss) { | |
2054 HandleScope scope(isolate); | |
2055 ASSERT(args.length() == 2); | |
2056 KeyedCallIC ic(isolate); | |
2057 Handle<Object> receiver = args.at<Object>(0); | |
2058 Handle<Object> key = args.at<Object>(1); | |
2059 ic.UpdateState(receiver, key); | |
2060 MaybeObject* maybe_result = ic.LoadFunction(receiver, key); | |
2061 // Result could be a function or a failure. | |
2062 JSFunction* raw_function = NULL; | |
2063 if (!maybe_result->To(&raw_function)) return maybe_result; | |
2064 | |
2065 if (raw_function->is_compiled()) return raw_function; | |
2066 | |
2067 Handle<JSFunction> function(raw_function, isolate); | |
2068 Compiler::EnsureCompiled(function, CLEAR_EXCEPTION); | |
2069 return *function; | |
2070 } | |
2071 | |
2072 | |
2073 // Used from ic-<arch>.cc. | 1728 // Used from ic-<arch>.cc. |
2074 RUNTIME_FUNCTION(MaybeObject*, LoadIC_Miss) { | 1729 RUNTIME_FUNCTION(MaybeObject*, LoadIC_Miss) { |
2075 HandleScope scope(isolate); | 1730 HandleScope scope(isolate); |
2076 ASSERT(args.length() == 2); | 1731 ASSERT(args.length() == 2); |
2077 LoadIC ic(IC::NO_EXTRA_FRAME, isolate); | 1732 LoadIC ic(IC::NO_EXTRA_FRAME, isolate); |
2078 Handle<Object> receiver = args.at<Object>(0); | 1733 Handle<Object> receiver = args.at<Object>(0); |
2079 Handle<String> key = args.at<String>(1); | 1734 Handle<String> key = args.at<String>(1); |
2080 ic.UpdateState(receiver, key); | 1735 ic.UpdateState(receiver, key); |
2081 return ic.Load(receiver, key); | 1736 return ic.Load(receiver, key); |
2082 } | 1737 } |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2121 HandleScope scope(isolate); | 1776 HandleScope scope(isolate); |
2122 ASSERT(args.length() == 3); | 1777 ASSERT(args.length() == 3); |
2123 StoreIC ic(IC::EXTRA_CALL_FRAME, isolate); | 1778 StoreIC ic(IC::EXTRA_CALL_FRAME, isolate); |
2124 Handle<Object> receiver = args.at<Object>(0); | 1779 Handle<Object> receiver = args.at<Object>(0); |
2125 Handle<String> key = args.at<String>(1); | 1780 Handle<String> key = args.at<String>(1); |
2126 ic.UpdateState(receiver, key); | 1781 ic.UpdateState(receiver, key); |
2127 return ic.Store(receiver, key, args.at<Object>(2)); | 1782 return ic.Store(receiver, key, args.at<Object>(2)); |
2128 } | 1783 } |
2129 | 1784 |
2130 | 1785 |
2131 RUNTIME_FUNCTION(MaybeObject*, KeyedCallIC_MissFromStubFailure) { | |
2132 HandleScope scope(isolate); | |
2133 ASSERT(args.length() == 2); | |
2134 KeyedCallIC ic(isolate); | |
2135 Arguments* caller_args = reinterpret_cast<Arguments*>(args[0]); | |
2136 Handle<Object> key = args.at<Object>(1); | |
2137 Handle<Object> receiver((*caller_args)[0], isolate); | |
2138 | |
2139 ic.UpdateState(receiver, key); | |
2140 MaybeObject* maybe_result = ic.LoadFunction(receiver, key); | |
2141 // Result could be a function or a failure. | |
2142 JSFunction* raw_function = NULL; | |
2143 if (!maybe_result->To(&raw_function)) return maybe_result; | |
2144 | |
2145 if (raw_function->is_compiled()) return raw_function; | |
2146 | |
2147 Handle<JSFunction> function(raw_function, isolate); | |
2148 Compiler::EnsureCompiled(function, CLEAR_EXCEPTION); | |
2149 return *function; | |
2150 } | |
2151 | |
2152 | |
2153 RUNTIME_FUNCTION(MaybeObject*, StoreIC_ArrayLength) { | 1786 RUNTIME_FUNCTION(MaybeObject*, StoreIC_ArrayLength) { |
2154 SealHandleScope shs(isolate); | 1787 SealHandleScope shs(isolate); |
2155 | 1788 |
2156 ASSERT(args.length() == 2); | 1789 ASSERT(args.length() == 2); |
2157 JSArray* receiver = JSArray::cast(args[0]); | 1790 JSArray* receiver = JSArray::cast(args[0]); |
2158 Object* len = args[1]; | 1791 Object* len = args[1]; |
2159 | 1792 |
2160 // The generated code should filter out non-Smis before we get here. | 1793 // The generated code should filter out non-Smis before we get here. |
2161 ASSERT(len->IsSmi()); | 1794 ASSERT(len->IsSmi()); |
2162 | 1795 |
(...skipping 1009 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3172 #undef ADDR | 2805 #undef ADDR |
3173 }; | 2806 }; |
3174 | 2807 |
3175 | 2808 |
3176 Address IC::AddressFromUtilityId(IC::UtilityId id) { | 2809 Address IC::AddressFromUtilityId(IC::UtilityId id) { |
3177 return IC_utilities[id]; | 2810 return IC_utilities[id]; |
3178 } | 2811 } |
3179 | 2812 |
3180 | 2813 |
3181 } } // namespace v8::internal | 2814 } } // namespace v8::internal |
OLD | NEW |