OLD | NEW |
---|---|
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 427 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
438 if (proto->IsNull()) { | 438 if (proto->IsNull()) { |
439 lookup->NotFound(); | 439 lookup->NotFound(); |
440 return; | 440 return; |
441 } | 441 } |
442 | 442 |
443 object = proto; | 443 object = proto; |
444 } | 444 } |
445 } | 445 } |
446 | 446 |
447 | 447 |
448 Object* CallICBase::TryCallAsFunction(Object* object) { | 448 Handle<Object> CallICBase::TryCallAsFunction(Handle<Object> object) { |
449 HandleScope scope(isolate()); | 449 Handle<Object> delegate = Execution::GetFunctionDelegate(object); |
450 Handle<Object> target(object, isolate()); | |
451 Handle<Object> delegate = Execution::GetFunctionDelegate(target); | |
452 | 450 |
453 if (delegate->IsJSFunction() && !object->IsJSFunctionProxy()) { | 451 if (delegate->IsJSFunction() && !object->IsJSFunctionProxy()) { |
454 // Patch the receiver and use the delegate as the function to | 452 // Patch the receiver and use the delegate as the function to |
455 // invoke. This is used for invoking objects as if they were | 453 // invoke. This is used for invoking objects as if they were functions. |
456 // functions. | 454 const int argc = target()->arguments_count(); |
457 const int argc = this->target()->arguments_count(); | |
458 StackFrameLocator locator; | 455 StackFrameLocator locator; |
459 JavaScriptFrame* frame = locator.FindJavaScriptFrame(0); | 456 JavaScriptFrame* frame = locator.FindJavaScriptFrame(0); |
460 int index = frame->ComputeExpressionsCount() - (argc + 1); | 457 int index = frame->ComputeExpressionsCount() - (argc + 1); |
461 frame->SetExpression(index, *target); | 458 frame->SetExpression(index, *object); |
462 } | 459 } |
463 | 460 |
464 return *delegate; | 461 return delegate; |
465 } | 462 } |
466 | 463 |
467 | 464 |
468 void CallICBase::ReceiverToObjectIfRequired(Handle<Object> callee, | 465 void CallICBase::ReceiverToObjectIfRequired(Handle<Object> callee, |
469 Handle<Object> object) { | 466 Handle<Object> object) { |
470 while (callee->IsJSFunctionProxy()) { | 467 while (callee->IsJSFunctionProxy()) { |
471 callee = Handle<Object>(JSFunctionProxy::cast(*callee)->call_trap()); | 468 callee = Handle<Object>(JSFunctionProxy::cast(*callee)->call_trap()); |
472 } | 469 } |
473 | 470 |
474 if (callee->IsJSFunction()) { | 471 if (callee->IsJSFunction()) { |
(...skipping 23 matching lines...) Expand all Loading... | |
498 // If the object is undefined or null it's illegal to try to get any | 495 // If the object is undefined or null it's illegal to try to get any |
499 // of its properties; throw a TypeError in that case. | 496 // of its properties; throw a TypeError in that case. |
500 if (object->IsUndefined() || object->IsNull()) { | 497 if (object->IsUndefined() || object->IsNull()) { |
501 return TypeError("non_object_property_call", object, name); | 498 return TypeError("non_object_property_call", object, name); |
502 } | 499 } |
503 | 500 |
504 // Check if the name is trivially convertible to an index and get | 501 // Check if the name is trivially convertible to an index and get |
505 // the element if so. | 502 // the element if so. |
506 uint32_t index; | 503 uint32_t index; |
507 if (name->AsArrayIndex(&index)) { | 504 if (name->AsArrayIndex(&index)) { |
508 Object* result; | 505 Handle<Object> result = Object::GetElement(object, index); |
509 { MaybeObject* maybe_result = object->GetElement(index); | 506 RETURN_IF_EMPTY_HANDLE(isolate(), result); |
510 if (!maybe_result->ToObject(&result)) return maybe_result; | 507 if (result->IsJSFunction()) return *result; |
511 } | |
512 | |
513 if (result->IsJSFunction()) return result; | |
514 | 508 |
515 // Try to find a suitable function delegate for the object at hand. | 509 // Try to find a suitable function delegate for the object at hand. |
516 result = TryCallAsFunction(result); | 510 result = TryCallAsFunction(result); |
517 if (result->IsJSFunction()) return result; | 511 if (result->IsJSFunction()) return *result; |
518 | 512 |
519 // Otherwise, it will fail in the lookup step. | 513 // Otherwise, it will fail in the lookup step. |
520 } | 514 } |
521 | 515 |
522 // Lookup the property in the object. | 516 // Lookup the property in the object. |
523 LookupResult lookup(isolate()); | 517 LookupResult lookup(isolate()); |
524 LookupForRead(*object, *name, &lookup); | 518 LookupForRead(object, name, &lookup); |
525 | 519 |
526 if (!lookup.IsProperty()) { | 520 if (!lookup.IsProperty()) { |
527 // If the object does not have the requested property, check which | 521 // If the object does not have the requested property, check which |
528 // exception we need to throw. | 522 // exception we need to throw. |
529 if (IsContextual(object)) { | 523 return IsContextual(object) |
530 return ReferenceError("not_defined", name); | 524 ? ReferenceError("not_defined", name) |
531 } | 525 : TypeError("undefined_method", object, name); |
532 return TypeError("undefined_method", object, name); | |
533 } | 526 } |
534 | 527 |
535 // Lookup is valid: Update inline cache and stub cache. | 528 // Lookup is valid: Update inline cache and stub cache. |
536 if (FLAG_use_ic) { | 529 if (FLAG_use_ic) { |
537 UpdateCaches(&lookup, state, extra_ic_state, object, name); | 530 UpdateCaches(&lookup, state, extra_ic_state, object, name); |
Kevin Millikin (Chromium)
2011/10/19 07:20:30
I stopped short of handlifying the UpdateCaches an
| |
538 } | 531 } |
539 | 532 |
540 // Get the property. | 533 // Get the property. |
541 PropertyAttributes attr; | 534 PropertyAttributes attr; |
542 Object* result; | 535 Handle<Object> result = |
543 { MaybeObject* maybe_result = | 536 Object::GetProperty(object, object, &lookup, name, &attr); |
544 object->GetProperty(*object, &lookup, *name, &attr); | 537 RETURN_IF_EMPTY_HANDLE(isolate(), result); |
545 if (!maybe_result->ToObject(&result)) return maybe_result; | |
546 } | |
547 | 538 |
548 if (lookup.type() == INTERCEPTOR) { | 539 if (lookup.type() == INTERCEPTOR && attr == ABSENT) { |
549 // If the object does not have the requested property, check which | 540 // If the object does not have the requested property, check which |
550 // exception we need to throw. | 541 // exception we need to throw. |
551 if (attr == ABSENT) { | 542 return IsContextual(object) |
552 if (IsContextual(object)) { | 543 ? ReferenceError("not_defined", name) |
553 return ReferenceError("not_defined", name); | 544 : TypeError("undefined_method", object, name); |
554 } | |
555 return TypeError("undefined_method", object, name); | |
556 } | |
557 } | 545 } |
558 | 546 |
559 ASSERT(!result->IsTheHole()); | 547 ASSERT(!result->IsTheHole()); |
560 | 548 |
561 HandleScope scope(isolate()); | |
562 // Wrap result in a handle because ReceiverToObjectIfRequired may allocate | |
563 // new object and cause GC. | |
564 Handle<Object> result_handle(result); | |
565 // Make receiver an object if the callee requires it. Strict mode or builtin | 549 // Make receiver an object if the callee requires it. Strict mode or builtin |
566 // functions do not wrap the receiver, non-strict functions and objects | 550 // functions do not wrap the receiver, non-strict functions and objects |
567 // called as functions do. | 551 // called as functions do. |
568 ReceiverToObjectIfRequired(result_handle, object); | 552 ReceiverToObjectIfRequired(result, object); |
569 | 553 |
570 if (result_handle->IsJSFunction()) { | 554 if (result->IsJSFunction()) { |
555 Handle<JSFunction> function = Handle<JSFunction>::cast(result); | |
571 #ifdef ENABLE_DEBUGGER_SUPPORT | 556 #ifdef ENABLE_DEBUGGER_SUPPORT |
572 // Handle stepping into a function if step into is active. | 557 // Handle stepping into a function if step into is active. |
573 Debug* debug = isolate()->debug(); | 558 Debug* debug = isolate()->debug(); |
574 if (debug->StepInActive()) { | 559 if (debug->StepInActive()) { |
575 // Protect the result in a handle as the debugger can allocate and might | 560 // Protect the result in a handle as the debugger can allocate and might |
576 // cause GC. | 561 // cause GC. |
577 Handle<JSFunction> function(JSFunction::cast(*result_handle), isolate()); | |
578 debug->HandleStepIn(function, object, fp(), false); | 562 debug->HandleStepIn(function, object, fp(), false); |
579 return *function; | |
580 } | 563 } |
581 #endif | 564 #endif |
582 | 565 return *function; |
583 return *result_handle; | |
584 } | 566 } |
585 | 567 |
586 // Try to find a suitable function delegate for the object at hand. | 568 // Try to find a suitable function delegate for the object at hand. |
587 result_handle = Handle<Object>(TryCallAsFunction(*result_handle)); | 569 result = TryCallAsFunction(result); |
588 if (result_handle->IsJSFunction()) return *result_handle; | 570 if (result->IsJSFunction()) return *result; |
589 | 571 |
590 return TypeError("property_not_function", object, name); | 572 return TypeError("property_not_function", object, name); |
591 } | 573 } |
592 | 574 |
593 | 575 |
594 bool CallICBase::TryUpdateExtraICState(LookupResult* lookup, | 576 bool CallICBase::TryUpdateExtraICState(LookupResult* lookup, |
595 Handle<Object> object, | 577 Handle<Object> object, |
596 Code::ExtraICState* extra_ic_state) { | 578 Code::ExtraICState* extra_ic_state) { |
597 ASSERT(kind_ == Code::CALL_IC); | 579 ASSERT(kind_ == Code::CALL_IC); |
598 if (lookup->type() != CONSTANT_FUNCTION) return false; | 580 if (lookup->type() != CONSTANT_FUNCTION) return false; |
(...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
820 object, | 802 object, |
821 Handle<String>::cast(key)); | 803 Handle<String>::cast(key)); |
822 } | 804 } |
823 | 805 |
824 if (object->IsUndefined() || object->IsNull()) { | 806 if (object->IsUndefined() || object->IsNull()) { |
825 return TypeError("non_object_property_call", object, key); | 807 return TypeError("non_object_property_call", object, key); |
826 } | 808 } |
827 | 809 |
828 if (FLAG_use_ic && state != MEGAMORPHIC && object->IsHeapObject()) { | 810 if (FLAG_use_ic && state != MEGAMORPHIC && object->IsHeapObject()) { |
829 int argc = target()->arguments_count(); | 811 int argc = target()->arguments_count(); |
830 Heap* heap = Handle<HeapObject>::cast(object)->GetHeap(); | 812 Handle<Map> map = |
831 Map* map = heap->non_strict_arguments_elements_map(); | 813 isolate()->factory()->non_strict_arguments_elements_map(); |
832 if (object->IsJSObject() && | 814 if (object->IsJSObject() && |
833 Handle<JSObject>::cast(object)->elements()->map() == map) { | 815 Handle<JSObject>::cast(object)->elements()->map() == *map) { |
834 MaybeObject* maybe_code = isolate()->stub_cache()->ComputeCallArguments( | 816 MaybeObject* maybe_code = isolate()->stub_cache()->ComputeCallArguments( |
835 argc, Code::KEYED_CALL_IC); | 817 argc, Code::KEYED_CALL_IC); |
836 Object* code; | 818 Code* code = NULL; |
837 if (maybe_code->ToObject(&code)) { | 819 if (maybe_code->To(&code)) { |
838 set_target(Code::cast(code)); | 820 set_target(code); |
839 #ifdef DEBUG | 821 #ifdef DEBUG |
840 TraceIC("KeyedCallIC", key, state, target()); | 822 TraceIC("KeyedCallIC", key, state, target()); |
841 #endif | 823 #endif |
842 } | 824 } |
843 } else if (FLAG_use_ic && state != MEGAMORPHIC && | 825 } else if (!object->IsAccessCheckNeeded()) { |
844 !object->IsAccessCheckNeeded()) { | |
845 MaybeObject* maybe_code = isolate()->stub_cache()->ComputeCallMegamorphic( | 826 MaybeObject* maybe_code = isolate()->stub_cache()->ComputeCallMegamorphic( |
846 argc, Code::KEYED_CALL_IC, Code::kNoExtraICState); | 827 argc, Code::KEYED_CALL_IC, Code::kNoExtraICState); |
847 Object* code; | 828 Code* code; |
848 if (maybe_code->ToObject(&code)) { | 829 if (maybe_code->To(&code)) { |
849 set_target(Code::cast(code)); | 830 set_target(code); |
850 #ifdef DEBUG | 831 #ifdef DEBUG |
851 TraceIC("KeyedCallIC", key, state, target()); | 832 TraceIC("KeyedCallIC", key, state, target()); |
852 #endif | 833 #endif |
853 } | 834 } |
854 } | 835 } |
855 } | 836 } |
856 | 837 |
857 HandleScope scope(isolate()); | |
858 Handle<Object> result = GetProperty(object, key); | 838 Handle<Object> result = GetProperty(object, key); |
859 RETURN_IF_EMPTY_HANDLE(isolate(), result); | 839 RETURN_IF_EMPTY_HANDLE(isolate(), result); |
860 | 840 |
861 // Make receiver an object if the callee requires it. Strict mode or builtin | 841 // Make receiver an object if the callee requires it. Strict mode or builtin |
862 // functions do not wrap the receiver, non-strict functions and objects | 842 // functions do not wrap the receiver, non-strict functions and objects |
863 // called as functions do. | 843 // called as functions do. |
864 ReceiverToObjectIfRequired(result, object); | 844 ReceiverToObjectIfRequired(result, object); |
845 if (result->IsJSFunction()) return *result; | |
865 | 846 |
866 if (result->IsJSFunction()) return *result; | 847 result = TryCallAsFunction(result); |
867 result = Handle<Object>(TryCallAsFunction(*result)); | |
868 if (result->IsJSFunction()) return *result; | 848 if (result->IsJSFunction()) return *result; |
869 | 849 |
870 return TypeError("property_not_function", object, key); | 850 return TypeError("property_not_function", object, key); |
871 } | 851 } |
872 | 852 |
873 | 853 |
874 MaybeObject* LoadIC::Load(State state, | 854 MaybeObject* LoadIC::Load(State state, |
875 Handle<Object> object, | 855 Handle<Object> object, |
876 Handle<String> name) { | 856 Handle<String> name) { |
877 // If the object is undefined or null it's illegal to try to get any | 857 // If the object is undefined or null it's illegal to try to get any |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
974 // Update inline cache and stub cache. | 954 // Update inline cache and stub cache. |
975 if (FLAG_use_ic) { | 955 if (FLAG_use_ic) { |
976 UpdateCaches(&lookup, state, object, name); | 956 UpdateCaches(&lookup, state, object, name); |
977 } | 957 } |
978 | 958 |
979 PropertyAttributes attr; | 959 PropertyAttributes attr; |
980 if (lookup.IsProperty() && | 960 if (lookup.IsProperty() && |
981 (lookup.type() == INTERCEPTOR || lookup.type() == HANDLER)) { | 961 (lookup.type() == INTERCEPTOR || lookup.type() == HANDLER)) { |
982 // Get the property. | 962 // Get the property. |
983 Handle<Object> result = | 963 Handle<Object> result = |
984 Object::GetProperty(isolate(), object, object, &lookup, name, &attr); | 964 Object::GetProperty(object, object, &lookup, name, &attr); |
985 RETURN_IF_EMPTY_HANDLE(isolate(), result); | 965 RETURN_IF_EMPTY_HANDLE(isolate(), result); |
986 // If the property is not present, check if we need to throw an | 966 // If the property is not present, check if we need to throw an |
987 // exception. | 967 // exception. |
988 if (attr == ABSENT && IsContextual(object)) { | 968 if (attr == ABSENT && IsContextual(object)) { |
989 return ReferenceError("not_defined", name); | 969 return ReferenceError("not_defined", name); |
990 } | 970 } |
991 return *result; | 971 return *result; |
992 } | 972 } |
993 | 973 |
994 // Get the property. | 974 // Get the property. |
(...skipping 1000 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1995 #ifdef DEBUG | 1975 #ifdef DEBUG |
1996 TraceIC("KeyedStoreIC", name, state, target()); | 1976 TraceIC("KeyedStoreIC", name, state, target()); |
1997 #endif | 1977 #endif |
1998 } | 1978 } |
1999 | 1979 |
2000 | 1980 |
2001 // ---------------------------------------------------------------------------- | 1981 // ---------------------------------------------------------------------------- |
2002 // Static IC stub generators. | 1982 // Static IC stub generators. |
2003 // | 1983 // |
2004 | 1984 |
2005 static JSFunction* CompileFunction(Isolate* isolate, | |
2006 JSFunction* function) { | |
2007 // Compile now with optimization. | |
2008 HandleScope scope(isolate); | |
2009 Handle<JSFunction> function_handle(function, isolate); | |
2010 CompileLazy(function_handle, CLEAR_EXCEPTION); | |
2011 return *function_handle; | |
2012 } | |
2013 | |
2014 | |
2015 // Used from ic-<arch>.cc. | 1985 // Used from ic-<arch>.cc. |
2016 RUNTIME_FUNCTION(MaybeObject*, CallIC_Miss) { | 1986 RUNTIME_FUNCTION(MaybeObject*, CallIC_Miss) { |
2017 NoHandleAllocation na; | 1987 HandleScope scope(isolate); |
2018 ASSERT(args.length() == 2); | 1988 ASSERT(args.length() == 2); |
2019 CallIC ic(isolate); | 1989 CallIC ic(isolate); |
2020 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); | 1990 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); |
2021 Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state(); | 1991 Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state(); |
2022 MaybeObject* maybe_result = ic.LoadFunction(state, | 1992 MaybeObject* maybe_result = ic.LoadFunction(state, |
2023 extra_ic_state, | 1993 extra_ic_state, |
2024 args.at<Object>(0), | 1994 args.at<Object>(0), |
2025 args.at<String>(1)); | 1995 args.at<String>(1)); |
2026 Object* result; | 1996 // Result could be a function or a failure. |
2027 if (!maybe_result->ToObject(&result)) return maybe_result; | 1997 JSFunction* raw_function = NULL; |
1998 if (!maybe_result->To(&raw_function)) return maybe_result; | |
2028 | 1999 |
2029 // The first time the inline cache is updated may be the first time the | 2000 // The first time the inline cache is updated may be the first time the |
2030 // function it references gets called. If the function was lazily compiled | 2001 // function it references gets called. If the function is lazily compiled |
2031 // then the first call will trigger a compilation. We check for this case | 2002 // then the first call will trigger a compilation. We check for this case |
2032 // and we do the compilation immediately, instead of waiting for the stub | 2003 // and we do the compilation immediately, instead of waiting for the stub |
2033 // currently attached to the JSFunction object to trigger compilation. We | 2004 // currently attached to the JSFunction object to trigger compilation. |
2034 // do this in the case where we know that the inline cache is inside a loop, | 2005 if (raw_function->is_compiled()) return raw_function; |
2035 // because then we know that we want to optimize the function. | 2006 |
2036 if (!result->IsJSFunction() || JSFunction::cast(result)->is_compiled()) { | 2007 Handle<JSFunction> function(raw_function); |
2037 return result; | 2008 JSFunction::CompileLazy(function, CLEAR_EXCEPTION); |
2038 } | 2009 return *function; |
2039 return CompileFunction(isolate, JSFunction::cast(result)); | |
2040 } | 2010 } |
2041 | 2011 |
2042 | 2012 |
2043 // Used from ic-<arch>.cc. | 2013 // Used from ic-<arch>.cc. |
2044 RUNTIME_FUNCTION(MaybeObject*, KeyedCallIC_Miss) { | 2014 RUNTIME_FUNCTION(MaybeObject*, KeyedCallIC_Miss) { |
2045 NoHandleAllocation na; | 2015 HandleScope scope(isolate); |
2046 ASSERT(args.length() == 2); | 2016 ASSERT(args.length() == 2); |
2047 KeyedCallIC ic(isolate); | 2017 KeyedCallIC ic(isolate); |
2048 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); | 2018 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); |
2049 Object* result; | 2019 MaybeObject* maybe_result = |
2050 { MaybeObject* maybe_result = | |
2051 ic.LoadFunction(state, args.at<Object>(0), args.at<Object>(1)); | 2020 ic.LoadFunction(state, args.at<Object>(0), args.at<Object>(1)); |
2052 if (!maybe_result->ToObject(&result)) return maybe_result; | 2021 // Result could be a function or a failure. |
2053 } | 2022 JSFunction* raw_function = NULL; |
2023 if (!maybe_result->To(&raw_function)) return maybe_result; | |
2054 | 2024 |
2055 if (!result->IsJSFunction() || JSFunction::cast(result)->is_compiled()) { | 2025 if (raw_function->is_compiled()) return raw_function; |
2056 return result; | 2026 |
2057 } | 2027 Handle<JSFunction> function(raw_function); |
2058 return CompileFunction(isolate, JSFunction::cast(result)); | 2028 JSFunction::CompileLazy(function, CLEAR_EXCEPTION); |
2029 return *function; | |
2059 } | 2030 } |
2060 | 2031 |
2061 | 2032 |
2062 // Used from ic-<arch>.cc. | 2033 // Used from ic-<arch>.cc. |
2063 RUNTIME_FUNCTION(MaybeObject*, LoadIC_Miss) { | 2034 RUNTIME_FUNCTION(MaybeObject*, LoadIC_Miss) { |
2064 HandleScope scope(isolate); | 2035 HandleScope scope(isolate); |
2065 ASSERT(args.length() == 2); | 2036 ASSERT(args.length() == 2); |
2066 LoadIC ic(isolate); | 2037 LoadIC ic(isolate); |
2067 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); | 2038 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); |
2068 return ic.Load(state, args.at<Object>(0), args.at<String>(1)); | 2039 return ic.Load(state, args.at<Object>(0), args.at<String>(1)); |
(...skipping 552 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2621 #undef ADDR | 2592 #undef ADDR |
2622 }; | 2593 }; |
2623 | 2594 |
2624 | 2595 |
2625 Address IC::AddressFromUtilityId(IC::UtilityId id) { | 2596 Address IC::AddressFromUtilityId(IC::UtilityId id) { |
2626 return IC_utilities[id]; | 2597 return IC_utilities[id]; |
2627 } | 2598 } |
2628 | 2599 |
2629 | 2600 |
2630 } } // namespace v8::internal | 2601 } } // namespace v8::internal |
OLD | NEW |