Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1)

Side by Side Diff: src/ic.cc

Issue 8345038: Handlify the runtime lookup of CallIC and KeyedCallIC. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 9 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698