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 521 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
532 // Change the receiver to the result of calling ToObject on it. | 532 // Change the receiver to the result of calling ToObject on it. |
533 const int argc = this->target()->arguments_count(); | 533 const int argc = this->target()->arguments_count(); |
534 StackFrameLocator locator(isolate()); | 534 StackFrameLocator locator(isolate()); |
535 JavaScriptFrame* frame = locator.FindJavaScriptFrame(0); | 535 JavaScriptFrame* frame = locator.FindJavaScriptFrame(0); |
536 int index = frame->ComputeExpressionsCount() - (argc + 1); | 536 int index = frame->ComputeExpressionsCount() - (argc + 1); |
537 frame->SetExpression(index, *isolate()->factory()->ToObject(object)); | 537 frame->SetExpression(index, *isolate()->factory()->ToObject(object)); |
538 } | 538 } |
539 } | 539 } |
540 | 540 |
541 | 541 |
542 MaybeObject* CallICBase::LoadFunction(Code::ExtraICState extra_ic_state, | 542 MaybeObject* CallICBase::LoadFunction(Handle<Object> object, |
543 Handle<Object> object, | |
544 Handle<String> name) { | 543 Handle<String> name) { |
545 bool use_ic = FLAG_use_ic; | 544 bool use_ic = FLAG_use_ic; |
546 if (object->IsJSObject()) { | 545 if (object->IsJSObject()) { |
547 Handle<JSObject> receiver = Handle<JSObject>::cast(object); | 546 Handle<JSObject> receiver = Handle<JSObject>::cast(object); |
548 if (receiver->map()->is_deprecated()) { | 547 if (receiver->map()->is_deprecated()) { |
549 use_ic = false; | 548 use_ic = false; |
550 JSObject::MigrateInstance(receiver); | 549 JSObject::MigrateInstance(receiver); |
551 } | 550 } |
552 } | 551 } |
553 | 552 |
(...skipping 24 matching lines...) Expand all Loading... |
578 | 577 |
579 if (!lookup.IsFound()) { | 578 if (!lookup.IsFound()) { |
580 // If the object does not have the requested property, check which | 579 // If the object does not have the requested property, check which |
581 // exception we need to throw. | 580 // exception we need to throw. |
582 return IsUndeclaredGlobal(object) | 581 return IsUndeclaredGlobal(object) |
583 ? ReferenceError("not_defined", name) | 582 ? ReferenceError("not_defined", name) |
584 : TypeError("undefined_method", object, name); | 583 : TypeError("undefined_method", object, name); |
585 } | 584 } |
586 | 585 |
587 // Lookup is valid: Update inline cache and stub cache. | 586 // Lookup is valid: Update inline cache and stub cache. |
588 if (use_ic) UpdateCaches(&lookup, extra_ic_state, object, name); | 587 if (use_ic) UpdateCaches(&lookup, object, name); |
589 | 588 |
590 // Get the property. | 589 // Get the property. |
591 PropertyAttributes attr; | 590 PropertyAttributes attr; |
592 Handle<Object> result = | 591 Handle<Object> result = |
593 Object::GetProperty(object, object, &lookup, name, &attr); | 592 Object::GetProperty(object, object, &lookup, name, &attr); |
594 RETURN_IF_EMPTY_HANDLE(isolate(), result); | 593 RETURN_IF_EMPTY_HANDLE(isolate(), result); |
595 | 594 |
596 if (lookup.IsInterceptor() && attr == ABSENT) { | 595 if (lookup.IsInterceptor() && attr == ABSENT) { |
597 // If the object does not have the requested property, check which | 596 // If the object does not have the requested property, check which |
598 // exception we need to throw. | 597 // exception we need to throw. |
(...skipping 24 matching lines...) Expand all Loading... |
623 } | 622 } |
624 | 623 |
625 // Try to find a suitable function delegate for the object at hand. | 624 // Try to find a suitable function delegate for the object at hand. |
626 result = TryCallAsFunction(result); | 625 result = TryCallAsFunction(result); |
627 if (result->IsJSFunction()) return *result; | 626 if (result->IsJSFunction()) return *result; |
628 | 627 |
629 return TypeError("property_not_function", object, name); | 628 return TypeError("property_not_function", object, name); |
630 } | 629 } |
631 | 630 |
632 | 631 |
633 bool CallICBase::TryUpdateExtraICState(LookupResult* lookup, | 632 bool CallIC::TryUpdateExtraICState(LookupResult* lookup, |
634 Handle<Object> object, | 633 Handle<Object> object) { |
635 Code::ExtraICState* extra_ic_state) { | |
636 ASSERT(kind_ == Code::CALL_IC); | |
637 if (!lookup->IsConstantFunction()) return false; | 634 if (!lookup->IsConstantFunction()) return false; |
638 JSFunction* function = lookup->GetConstantFunction(); | 635 JSFunction* function = lookup->GetConstantFunction(); |
639 if (!function->shared()->HasBuiltinFunctionId()) return false; | 636 if (!function->shared()->HasBuiltinFunctionId()) return false; |
640 | 637 |
641 // Fetch the arguments passed to the called function. | 638 // Fetch the arguments passed to the called function. |
642 const int argc = target()->arguments_count(); | 639 const int argc = target()->arguments_count(); |
643 Address entry = isolate()->c_entry_fp(isolate()->thread_local_top()); | 640 Address entry = isolate()->c_entry_fp(isolate()->thread_local_top()); |
644 Address fp = Memory::Address_at(entry + ExitFrameConstants::kCallerFPOffset); | 641 Address fp = Memory::Address_at(entry + ExitFrameConstants::kCallerFPOffset); |
645 Arguments args(argc + 1, | 642 Arguments args(argc + 1, |
646 &Memory::Object_at(fp + | 643 &Memory::Object_at(fp + |
647 StandardFrameConstants::kCallerSPOffset + | 644 StandardFrameConstants::kCallerSPOffset + |
648 argc * kPointerSize)); | 645 argc * kPointerSize)); |
649 switch (function->shared()->builtin_function_id()) { | 646 switch (function->shared()->builtin_function_id()) { |
650 case kStringCharCodeAt: | 647 case kStringCharCodeAt: |
651 case kStringCharAt: | 648 case kStringCharAt: |
652 if (object->IsString()) { | 649 if (object->IsString()) { |
653 String* string = String::cast(*object); | 650 String* string = String::cast(*object); |
654 // Check there's the right string value or wrapper in the receiver slot. | 651 // Check there's the right string value or wrapper in the receiver slot. |
655 ASSERT(string == args[0] || string == JSValue::cast(args[0])->value()); | 652 ASSERT(string == args[0] || string == JSValue::cast(args[0])->value()); |
656 // If we're in the default (fastest) state and the index is | 653 // If we're in the default (fastest) state and the index is |
657 // out of bounds, update the state to record this fact. | 654 // out of bounds, update the state to record this fact. |
658 if (StringStubState::decode(*extra_ic_state) == DEFAULT_STRING_STUB && | 655 if (StringStubState::decode(extra_ic_state()) == DEFAULT_STRING_STUB && |
659 argc >= 1 && args[1]->IsNumber()) { | 656 argc >= 1 && args[1]->IsNumber()) { |
660 double index = DoubleToInteger(args.number_at(1)); | 657 double index = DoubleToInteger(args.number_at(1)); |
661 if (index < 0 || index >= string->length()) { | 658 if (index < 0 || index >= string->length()) { |
662 *extra_ic_state = | 659 extra_ic_state_ = |
663 StringStubState::update(*extra_ic_state, | 660 StringStubState::update(extra_ic_state(), |
664 STRING_INDEX_OUT_OF_BOUNDS); | 661 STRING_INDEX_OUT_OF_BOUNDS); |
665 return true; | 662 return true; |
666 } | 663 } |
667 } | 664 } |
668 } | 665 } |
669 break; | 666 break; |
670 default: | 667 default: |
671 return false; | 668 return false; |
672 } | 669 } |
673 return false; | 670 return false; |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
723 ASSERT(HasInterceptorGetter(*holder)); | 720 ASSERT(HasInterceptorGetter(*holder)); |
724 return isolate()->stub_cache()->ComputeCallInterceptor( | 721 return isolate()->stub_cache()->ComputeCallInterceptor( |
725 argc, kind_, extra_state, name, object, holder); | 722 argc, kind_, extra_state, name, object, holder); |
726 default: | 723 default: |
727 return Handle<Code>::null(); | 724 return Handle<Code>::null(); |
728 } | 725 } |
729 } | 726 } |
730 | 727 |
731 | 728 |
732 void CallICBase::UpdateCaches(LookupResult* lookup, | 729 void CallICBase::UpdateCaches(LookupResult* lookup, |
733 Code::ExtraICState extra_ic_state, | |
734 Handle<Object> object, | 730 Handle<Object> object, |
735 Handle<String> name) { | 731 Handle<String> name) { |
736 // Bail out if we didn't find a result. | 732 // Bail out if we didn't find a result. |
737 if (!lookup->IsProperty() || !lookup->IsCacheable()) return; | 733 if (!lookup->IsProperty() || !lookup->IsCacheable()) return; |
738 | 734 |
739 // Compute the number of arguments. | 735 // Compute the number of arguments. |
740 int argc = target()->arguments_count(); | 736 int argc = target()->arguments_count(); |
741 Handle<Code> code; | 737 Handle<Code> code; |
742 if (state() == UNINITIALIZED) { | 738 if (state() == UNINITIALIZED) { |
743 // This is the first time we execute this inline cache. | 739 // This is the first time we execute this inline cache. |
744 // Set the target to the pre monomorphic stub to delay | 740 // Set the target to the pre monomorphic stub to delay |
745 // setting the monomorphic state. | 741 // setting the monomorphic state. |
746 code = isolate()->stub_cache()->ComputeCallPreMonomorphic( | 742 code = isolate()->stub_cache()->ComputeCallPreMonomorphic( |
747 argc, kind_, extra_ic_state); | 743 argc, kind_, extra_ic_state()); |
748 } else if (state() == MONOMORPHIC) { | 744 } else if (state() == MONOMORPHIC) { |
749 if (kind_ == Code::CALL_IC && | 745 if (kind_ == Code::CALL_IC && |
750 TryUpdateExtraICState(lookup, object, &extra_ic_state)) { | 746 static_cast<CallIC*>(this)->TryUpdateExtraICState(lookup, object)) { |
751 code = ComputeMonomorphicStub(lookup, extra_ic_state, object, name); | 747 code = ComputeMonomorphicStub(lookup, extra_ic_state(), object, name); |
752 } else if (TryRemoveInvalidPrototypeDependentStub(*object, *name)) { | 748 } else if (TryRemoveInvalidPrototypeDependentStub(*object, *name)) { |
753 MarkMonomorphicPrototypeFailure(); | 749 MarkMonomorphicPrototypeFailure(); |
754 code = ComputeMonomorphicStub(lookup, extra_ic_state, object, name); | 750 code = ComputeMonomorphicStub(lookup, extra_ic_state(), object, name); |
755 } else { | 751 } else { |
756 code = isolate()->stub_cache()->ComputeCallMegamorphic( | 752 code = isolate()->stub_cache()->ComputeCallMegamorphic( |
757 argc, kind_, extra_ic_state); | 753 argc, kind_, extra_ic_state()); |
758 } | 754 } |
759 } else { | 755 } else { |
760 code = ComputeMonomorphicStub(lookup, extra_ic_state, object, name); | 756 code = ComputeMonomorphicStub(lookup, extra_ic_state(), object, name); |
761 } | 757 } |
762 | 758 |
763 // If there's no appropriate stub we simply avoid updating the caches. | 759 // If there's no appropriate stub we simply avoid updating the caches. |
764 if (code.is_null()) return; | 760 if (code.is_null()) return; |
765 | 761 |
766 // Patch the call site depending on the state of the cache. | 762 // Patch the call site depending on the state of the cache. |
767 switch (state()) { | 763 switch (state()) { |
768 case UNINITIALIZED: | 764 case UNINITIALIZED: |
769 case MONOMORPHIC_PROTOTYPE_FAILURE: | 765 case MONOMORPHIC_PROTOTYPE_FAILURE: |
770 case PREMONOMORPHIC: | 766 case PREMONOMORPHIC: |
(...skipping 19 matching lines...) Expand all Loading... |
790 break; | 786 break; |
791 } | 787 } |
792 | 788 |
793 TRACE_IC(kind_ == Code::CALL_IC ? "CallIC" : "KeyedCallIC", name, target()); | 789 TRACE_IC(kind_ == Code::CALL_IC ? "CallIC" : "KeyedCallIC", name, target()); |
794 } | 790 } |
795 | 791 |
796 | 792 |
797 MaybeObject* KeyedCallIC::LoadFunction(Handle<Object> object, | 793 MaybeObject* KeyedCallIC::LoadFunction(Handle<Object> object, |
798 Handle<Object> key) { | 794 Handle<Object> key) { |
799 if (key->IsInternalizedString()) { | 795 if (key->IsInternalizedString()) { |
800 return CallICBase::LoadFunction(Code::kNoExtraICState, | 796 return CallICBase::LoadFunction(object, Handle<String>::cast(key)); |
801 object, | |
802 Handle<String>::cast(key)); | |
803 } | 797 } |
804 | 798 |
805 bool use_ic = FLAG_use_ic && !object->IsAccessCheckNeeded(); | 799 bool use_ic = FLAG_use_ic && !object->IsAccessCheckNeeded(); |
806 if (object->IsJSObject()) { | 800 if (object->IsJSObject()) { |
807 Handle<JSObject> receiver = Handle<JSObject>::cast(object); | 801 Handle<JSObject> receiver = Handle<JSObject>::cast(object); |
808 if (receiver->map()->is_deprecated()) { | 802 if (receiver->map()->is_deprecated()) { |
809 use_ic = false; | 803 use_ic = false; |
810 JSObject::MigrateInstance(receiver); | 804 JSObject::MigrateInstance(receiver); |
811 } | 805 } |
812 } | 806 } |
(...skipping 1294 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2107 // ---------------------------------------------------------------------------- | 2101 // ---------------------------------------------------------------------------- |
2108 // Static IC stub generators. | 2102 // Static IC stub generators. |
2109 // | 2103 // |
2110 | 2104 |
2111 // Used from ic-<arch>.cc. | 2105 // Used from ic-<arch>.cc. |
2112 RUNTIME_FUNCTION(MaybeObject*, CallIC_Miss) { | 2106 RUNTIME_FUNCTION(MaybeObject*, CallIC_Miss) { |
2113 HandleScope scope(isolate); | 2107 HandleScope scope(isolate); |
2114 ASSERT(args.length() == 2); | 2108 ASSERT(args.length() == 2); |
2115 CallIC ic(isolate); | 2109 CallIC ic(isolate); |
2116 ic.UpdateState(args[0], args[1]); | 2110 ic.UpdateState(args[0], args[1]); |
2117 Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state(); | 2111 MaybeObject* maybe_result = ic.LoadFunction(args.at<Object>(0), |
2118 MaybeObject* maybe_result = ic.LoadFunction(extra_ic_state, | |
2119 args.at<Object>(0), | |
2120 args.at<String>(1)); | 2112 args.at<String>(1)); |
2121 JSFunction* raw_function; | 2113 JSFunction* raw_function; |
2122 if (!maybe_result->To(&raw_function)) return maybe_result; | 2114 if (!maybe_result->To(&raw_function)) return maybe_result; |
2123 | 2115 |
2124 // The first time the inline cache is updated may be the first time the | 2116 // The first time the inline cache is updated may be the first time the |
2125 // function it references gets called. If the function is lazily compiled | 2117 // function it references gets called. If the function is lazily compiled |
2126 // then the first call will trigger a compilation. We check for this case | 2118 // then the first call will trigger a compilation. We check for this case |
2127 // and we do the compilation immediately, instead of waiting for the stub | 2119 // and we do the compilation immediately, instead of waiting for the stub |
2128 // currently attached to the JSFunction object to trigger compilation. | 2120 // currently attached to the JSFunction object to trigger compilation. |
2129 if (raw_function->is_compiled()) return raw_function; | 2121 if (raw_function->is_compiled()) return raw_function; |
(...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2313 args.at<Object>(1), | 2305 args.at<Object>(1), |
2314 args.at<Object>(2), | 2306 args.at<Object>(2), |
2315 MISS); | 2307 MISS); |
2316 } | 2308 } |
2317 | 2309 |
2318 | 2310 |
2319 RUNTIME_FUNCTION(MaybeObject*, StoreIC_Slow) { | 2311 RUNTIME_FUNCTION(MaybeObject*, StoreIC_Slow) { |
2320 HandleScope scope(isolate); | 2312 HandleScope scope(isolate); |
2321 ASSERT(args.length() == 3); | 2313 ASSERT(args.length() == 3); |
2322 StoreIC ic(IC::NO_EXTRA_FRAME, isolate); | 2314 StoreIC ic(IC::NO_EXTRA_FRAME, isolate); |
2323 Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state(); | |
2324 Handle<Object> object = args.at<Object>(0); | 2315 Handle<Object> object = args.at<Object>(0); |
2325 Handle<Object> key = args.at<Object>(1); | 2316 Handle<Object> key = args.at<Object>(1); |
2326 Handle<Object> value = args.at<Object>(2); | 2317 Handle<Object> value = args.at<Object>(2); |
2327 StrictModeFlag strict_mode = Code::GetStrictMode(extra_ic_state); | 2318 StrictModeFlag strict_mode = ic.strict_mode(); |
2328 return Runtime::SetObjectProperty(isolate, | 2319 return Runtime::SetObjectProperty(isolate, |
2329 object, | 2320 object, |
2330 key, | 2321 key, |
2331 value, | 2322 value, |
2332 NONE, | 2323 NONE, |
2333 strict_mode); | 2324 strict_mode); |
2334 } | 2325 } |
2335 | 2326 |
2336 | 2327 |
2337 RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_Slow) { | 2328 RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_Slow) { |
2338 HandleScope scope(isolate); | 2329 HandleScope scope(isolate); |
2339 ASSERT(args.length() == 3); | 2330 ASSERT(args.length() == 3); |
2340 KeyedStoreIC ic(IC::NO_EXTRA_FRAME, isolate); | 2331 KeyedStoreIC ic(IC::NO_EXTRA_FRAME, isolate); |
2341 Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state(); | |
2342 Handle<Object> object = args.at<Object>(0); | 2332 Handle<Object> object = args.at<Object>(0); |
2343 Handle<Object> key = args.at<Object>(1); | 2333 Handle<Object> key = args.at<Object>(1); |
2344 Handle<Object> value = args.at<Object>(2); | 2334 Handle<Object> value = args.at<Object>(2); |
2345 StrictModeFlag strict_mode = Code::GetStrictMode(extra_ic_state); | 2335 StrictModeFlag strict_mode = ic.strict_mode(); |
2346 return Runtime::SetObjectProperty(isolate, | 2336 return Runtime::SetObjectProperty(isolate, |
2347 object, | 2337 object, |
2348 key, | 2338 key, |
2349 value, | 2339 value, |
2350 NONE, | 2340 NONE, |
2351 strict_mode); | 2341 strict_mode); |
2352 } | 2342 } |
2353 | 2343 |
2354 | 2344 |
2355 RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_MissForceGeneric) { | 2345 RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_MissForceGeneric) { |
2356 HandleScope scope(isolate); | 2346 HandleScope scope(isolate); |
2357 ASSERT(args.length() == 3); | 2347 ASSERT(args.length() == 3); |
2358 KeyedStoreIC ic(IC::NO_EXTRA_FRAME, isolate); | 2348 KeyedStoreIC ic(IC::NO_EXTRA_FRAME, isolate); |
2359 ic.UpdateState(args[0], args[1]); | 2349 ic.UpdateState(args[0], args[1]); |
2360 return ic.Store(args.at<Object>(0), | 2350 return ic.Store(args.at<Object>(0), |
2361 args.at<Object>(1), | 2351 args.at<Object>(1), |
2362 args.at<Object>(2), | 2352 args.at<Object>(2), |
2363 MISS_FORCE_GENERIC); | 2353 MISS_FORCE_GENERIC); |
2364 } | 2354 } |
2365 | 2355 |
2366 | 2356 |
2367 RUNTIME_FUNCTION(MaybeObject*, ElementsTransitionAndStoreIC_Miss) { | 2357 RUNTIME_FUNCTION(MaybeObject*, ElementsTransitionAndStoreIC_Miss) { |
2368 HandleScope scope(isolate); | 2358 HandleScope scope(isolate); |
2369 ASSERT(args.length() == 4); | 2359 ASSERT(args.length() == 4); |
2370 KeyedStoreIC ic(IC::EXTRA_CALL_FRAME, isolate); | 2360 KeyedStoreIC ic(IC::EXTRA_CALL_FRAME, isolate); |
2371 Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state(); | |
2372 Handle<Object> value = args.at<Object>(0); | 2361 Handle<Object> value = args.at<Object>(0); |
2373 Handle<Object> key = args.at<Object>(2); | 2362 Handle<Object> key = args.at<Object>(2); |
2374 Handle<Object> object = args.at<Object>(3); | 2363 Handle<Object> object = args.at<Object>(3); |
2375 StrictModeFlag strict_mode = Code::GetStrictMode(extra_ic_state); | 2364 StrictModeFlag strict_mode = ic.strict_mode(); |
2376 return Runtime::SetObjectProperty(isolate, | 2365 return Runtime::SetObjectProperty(isolate, |
2377 object, | 2366 object, |
2378 key, | 2367 key, |
2379 value, | 2368 value, |
2380 NONE, | 2369 NONE, |
2381 strict_mode); | 2370 strict_mode); |
2382 } | 2371 } |
2383 | 2372 |
2384 | 2373 |
2385 void BinaryOpIC::patch(Code* code) { | 2374 void BinaryOpIC::patch(Code* code) { |
(...skipping 592 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2978 #undef ADDR | 2967 #undef ADDR |
2979 }; | 2968 }; |
2980 | 2969 |
2981 | 2970 |
2982 Address IC::AddressFromUtilityId(IC::UtilityId id) { | 2971 Address IC::AddressFromUtilityId(IC::UtilityId id) { |
2983 return IC_utilities[id]; | 2972 return IC_utilities[id]; |
2984 } | 2973 } |
2985 | 2974 |
2986 | 2975 |
2987 } } // namespace v8::internal | 2976 } } // namespace v8::internal |
OLD | NEW |