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

Side by Side Diff: src/ic.cc

Issue 3970005: Make Failure inherit from MaybeObject instead of Object. (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 10 years, 1 month 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
« no previous file with comments | « src/ic.h ('k') | src/liveedit.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2006-2009 the V8 project authors. All rights reserved. 1 // Copyright 2006-2009 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 458 matching lines...) Expand 10 before | Expand all | Expand 10 after
469 469
470 // Change the receiver to the result of calling ToObject on it. 470 // Change the receiver to the result of calling ToObject on it.
471 const int argc = this->target()->arguments_count(); 471 const int argc = this->target()->arguments_count();
472 StackFrameLocator locator; 472 StackFrameLocator locator;
473 JavaScriptFrame* frame = locator.FindJavaScriptFrame(0); 473 JavaScriptFrame* frame = locator.FindJavaScriptFrame(0);
474 int index = frame->ComputeExpressionsCount() - (argc + 1); 474 int index = frame->ComputeExpressionsCount() - (argc + 1);
475 frame->SetExpression(index, *Factory::ToObject(object)); 475 frame->SetExpression(index, *Factory::ToObject(object));
476 } 476 }
477 477
478 478
479 Object* CallICBase::LoadFunction(State state, 479 MaybeObject* CallICBase::LoadFunction(State state,
480 Handle<Object> object, 480 Handle<Object> object,
481 Handle<String> name) { 481 Handle<String> name) {
482 // If the object is undefined or null it's illegal to try to get any 482 // If the object is undefined or null it's illegal to try to get any
483 // of its properties; throw a TypeError in that case. 483 // of its properties; throw a TypeError in that case.
484 if (object->IsUndefined() || object->IsNull()) { 484 if (object->IsUndefined() || object->IsNull()) {
485 return TypeError("non_object_property_call", object, name); 485 return TypeError("non_object_property_call", object, name);
486 } 486 }
487 487
488 if (object->IsString() || object->IsNumber() || object->IsBoolean()) { 488 if (object->IsString() || object->IsNumber() || object->IsBoolean()) {
489 ReceiverToObject(object); 489 ReceiverToObject(object);
490 } 490 }
491 491
492 // Check if the name is trivially convertible to an index and get 492 // Check if the name is trivially convertible to an index and get
493 // the element if so. 493 // the element if so.
494 uint32_t index; 494 uint32_t index;
495 if (name->AsArrayIndex(&index)) { 495 if (name->AsArrayIndex(&index)) {
496 Object* result = object->GetElement(index); 496 Object* result;
497 { MaybeObject* maybe_result = object->GetElement(index);
498 if (!maybe_result->ToObject(&result)) return maybe_result;
499 }
500
497 if (result->IsJSFunction()) return result; 501 if (result->IsJSFunction()) return result;
498 502
499 // Try to find a suitable function delegate for the object at hand. 503 // Try to find a suitable function delegate for the object at hand.
500 result = TryCallAsFunction(result); 504 result = TryCallAsFunction(result);
501 if (result->IsJSFunction()) return result; 505 if (result->IsJSFunction()) return result;
502 506
503 // Otherwise, it will fail in the lookup step. 507 // Otherwise, it will fail in the lookup step.
504 } 508 }
505 509
506 // Lookup the property in the object. 510 // Lookup the property in the object.
507 LookupResult lookup; 511 LookupResult lookup;
508 LookupForRead(*object, *name, &lookup); 512 LookupForRead(*object, *name, &lookup);
509 513
510 if (!lookup.IsProperty()) { 514 if (!lookup.IsProperty()) {
511 // If the object does not have the requested property, check which 515 // If the object does not have the requested property, check which
512 // exception we need to throw. 516 // exception we need to throw.
513 if (IsContextual(object)) { 517 if (IsContextual(object)) {
514 return ReferenceError("not_defined", name); 518 return ReferenceError("not_defined", name);
515 } 519 }
516 return TypeError("undefined_method", object, name); 520 return TypeError("undefined_method", object, name);
517 } 521 }
518 522
519 // Lookup is valid: Update inline cache and stub cache. 523 // Lookup is valid: Update inline cache and stub cache.
520 if (FLAG_use_ic) { 524 if (FLAG_use_ic) {
521 UpdateCaches(&lookup, state, object, name); 525 UpdateCaches(&lookup, state, object, name);
522 } 526 }
523 527
524 // Get the property. 528 // Get the property.
525 PropertyAttributes attr; 529 PropertyAttributes attr;
526 Object* result = object->GetProperty(*object, &lookup, *name, &attr); 530 Object* result;
527 if (result->IsFailure()) return result; 531 { MaybeObject* maybe_result =
532 object->GetProperty(*object, &lookup, *name, &attr);
533 if (!maybe_result->ToObject(&result)) return maybe_result;
534 }
528 if (lookup.type() == INTERCEPTOR) { 535 if (lookup.type() == INTERCEPTOR) {
529 // If the object does not have the requested property, check which 536 // If the object does not have the requested property, check which
530 // exception we need to throw. 537 // exception we need to throw.
531 if (attr == ABSENT) { 538 if (attr == ABSENT) {
532 if (IsContextual(object)) { 539 if (IsContextual(object)) {
533 return ReferenceError("not_defined", name); 540 return ReferenceError("not_defined", name);
534 } 541 }
535 return TypeError("undefined_method", object, name); 542 return TypeError("undefined_method", object, name);
536 } 543 }
537 } 544 }
(...skipping 11 matching lines...) Expand all
549 Debug::HandleStepIn(function, object, fp(), false); 556 Debug::HandleStepIn(function, object, fp(), false);
550 return *function; 557 return *function;
551 } 558 }
552 #endif 559 #endif
553 560
554 return result; 561 return result;
555 } 562 }
556 563
557 // Try to find a suitable function delegate for the object at hand. 564 // Try to find a suitable function delegate for the object at hand.
558 result = TryCallAsFunction(result); 565 result = TryCallAsFunction(result);
559 return result->IsJSFunction() ? 566 MaybeObject* answer = result;
560 result : TypeError("property_not_function", object, name); 567 if (!result->IsJSFunction()) {
568 answer = TypeError("property_not_function", object, name);
569 }
570 return answer;
561 } 571 }
562 572
563 573
564 void CallICBase::UpdateCaches(LookupResult* lookup, 574 void CallICBase::UpdateCaches(LookupResult* lookup,
565 State state, 575 State state,
566 Handle<Object> object, 576 Handle<Object> object,
567 Handle<String> name) { 577 Handle<String> name) {
568 // Bail out if we didn't find a result. 578 // Bail out if we didn't find a result.
569 if (!lookup->IsProperty() || !lookup->IsCacheable()) return; 579 if (!lookup->IsProperty() || !lookup->IsCacheable()) return;
570 580
571 if (lookup->holder() != *object && 581 if (lookup->holder() != *object &&
572 HasNormalObjectsInPrototypeChain(lookup, object->GetPrototype())) { 582 HasNormalObjectsInPrototypeChain(lookup, object->GetPrototype())) {
573 // Suppress optimization for prototype chains with slow properties objects 583 // Suppress optimization for prototype chains with slow properties objects
574 // in the middle. 584 // in the middle.
575 return; 585 return;
576 } 586 }
577 587
578 // Compute the number of arguments. 588 // Compute the number of arguments.
579 int argc = target()->arguments_count(); 589 int argc = target()->arguments_count();
580 InLoopFlag in_loop = target()->ic_in_loop(); 590 InLoopFlag in_loop = target()->ic_in_loop();
581 Object* code = NULL; 591 MaybeObject* maybe_code = NULL;
582 592 Object* code;
583 if (state == UNINITIALIZED) { 593 if (state == UNINITIALIZED) {
584 // This is the first time we execute this inline cache. 594 // This is the first time we execute this inline cache.
585 // Set the target to the pre monomorphic stub to delay 595 // Set the target to the pre monomorphic stub to delay
586 // setting the monomorphic state. 596 // setting the monomorphic state.
587 code = StubCache::ComputeCallPreMonomorphic(argc, in_loop, kind_); 597 maybe_code = StubCache::ComputeCallPreMonomorphic(argc, in_loop, kind_);
588 } else if (state == MONOMORPHIC) { 598 } else if (state == MONOMORPHIC) {
589 code = StubCache::ComputeCallMegamorphic(argc, in_loop, kind_); 599 maybe_code = StubCache::ComputeCallMegamorphic(argc, in_loop, kind_);
590 } else { 600 } else {
591 // Compute monomorphic stub. 601 // Compute monomorphic stub.
592 switch (lookup->type()) { 602 switch (lookup->type()) {
593 case FIELD: { 603 case FIELD: {
594 int index = lookup->GetFieldIndex(); 604 int index = lookup->GetFieldIndex();
595 code = StubCache::ComputeCallField(argc, 605 maybe_code = StubCache::ComputeCallField(argc,
596 in_loop, 606 in_loop,
597 kind_, 607 kind_,
598 *name, 608 *name,
599 *object, 609 *object,
600 lookup->holder(), 610 lookup->holder(),
601 index); 611 index);
602 break; 612 break;
603 } 613 }
604 case CONSTANT_FUNCTION: { 614 case CONSTANT_FUNCTION: {
605 // Get the constant function and compute the code stub for this 615 // Get the constant function and compute the code stub for this
606 // call; used for rewriting to monomorphic state and making sure 616 // call; used for rewriting to monomorphic state and making sure
607 // that the code stub is in the stub cache. 617 // that the code stub is in the stub cache.
608 JSFunction* function = lookup->GetConstantFunction(); 618 JSFunction* function = lookup->GetConstantFunction();
609 code = StubCache::ComputeCallConstant(argc, 619 maybe_code = StubCache::ComputeCallConstant(argc,
610 in_loop, 620 in_loop,
611 kind_, 621 kind_,
612 *name, 622 *name,
613 *object, 623 *object,
614 lookup->holder(), 624 lookup->holder(),
615 function); 625 function);
616 break; 626 break;
617 } 627 }
618 case NORMAL: { 628 case NORMAL: {
619 if (!object->IsJSObject()) return; 629 if (!object->IsJSObject()) return;
620 Handle<JSObject> receiver = Handle<JSObject>::cast(object); 630 Handle<JSObject> receiver = Handle<JSObject>::cast(object);
621 631
622 if (lookup->holder()->IsGlobalObject()) { 632 if (lookup->holder()->IsGlobalObject()) {
623 GlobalObject* global = GlobalObject::cast(lookup->holder()); 633 GlobalObject* global = GlobalObject::cast(lookup->holder());
624 JSGlobalPropertyCell* cell = 634 JSGlobalPropertyCell* cell =
625 JSGlobalPropertyCell::cast(global->GetPropertyCell(lookup)); 635 JSGlobalPropertyCell::cast(global->GetPropertyCell(lookup));
626 if (!cell->value()->IsJSFunction()) return; 636 if (!cell->value()->IsJSFunction()) return;
627 JSFunction* function = JSFunction::cast(cell->value()); 637 JSFunction* function = JSFunction::cast(cell->value());
628 code = StubCache::ComputeCallGlobal(argc, 638 maybe_code = StubCache::ComputeCallGlobal(argc,
629 in_loop, 639 in_loop,
630 kind_, 640 kind_,
631 *name, 641 *name,
632 *receiver, 642 *receiver,
633 global, 643 global,
634 cell, 644 cell,
635 function); 645 function);
636 } else { 646 } else {
637 // There is only one shared stub for calling normalized 647 // There is only one shared stub for calling normalized
638 // properties. It does not traverse the prototype chain, so the 648 // properties. It does not traverse the prototype chain, so the
639 // property must be found in the receiver for the stub to be 649 // property must be found in the receiver for the stub to be
640 // applicable. 650 // applicable.
641 if (lookup->holder() != *receiver) return; 651 if (lookup->holder() != *receiver) return;
642 code = StubCache::ComputeCallNormal(argc, 652 maybe_code = StubCache::ComputeCallNormal(argc,
643 in_loop, 653 in_loop,
644 kind_, 654 kind_,
645 *name, 655 *name,
646 *receiver); 656 *receiver);
647 } 657 }
648 break; 658 break;
649 } 659 }
650 case INTERCEPTOR: { 660 case INTERCEPTOR: {
651 ASSERT(HasInterceptorGetter(lookup->holder())); 661 ASSERT(HasInterceptorGetter(lookup->holder()));
652 code = StubCache::ComputeCallInterceptor(argc, 662 maybe_code = StubCache::ComputeCallInterceptor(argc,
653 kind_, 663 kind_,
654 *name, 664 *name,
655 *object, 665 *object,
656 lookup->holder()); 666 lookup->holder());
657 break; 667 break;
658 } 668 }
659 default: 669 default:
660 return; 670 return;
661 } 671 }
662 } 672 }
663 673
664 // If we're unable to compute the stub (not enough memory left), we 674 // If we're unable to compute the stub (not enough memory left), we
665 // simply avoid updating the caches. 675 // simply avoid updating the caches.
666 if (code == NULL || code->IsFailure()) return; 676 if (maybe_code == NULL || !maybe_code->ToObject(&code)) return;
667 677
668 // Patch the call site depending on the state of the cache. 678 // Patch the call site depending on the state of the cache.
669 if (state == UNINITIALIZED || 679 if (state == UNINITIALIZED ||
670 state == PREMONOMORPHIC || 680 state == PREMONOMORPHIC ||
671 state == MONOMORPHIC || 681 state == MONOMORPHIC ||
672 state == MONOMORPHIC_PROTOTYPE_FAILURE) { 682 state == MONOMORPHIC_PROTOTYPE_FAILURE) {
673 set_target(Code::cast(code)); 683 set_target(Code::cast(code));
674 } else if (state == MEGAMORPHIC) { 684 } else if (state == MEGAMORPHIC) {
675 // Cache code holding map should be consistent with 685 // Cache code holding map should be consistent with
676 // GenerateMonomorphicCacheProbe. It is not the map which holds the stub. 686 // GenerateMonomorphicCacheProbe. It is not the map which holds the stub.
677 Map* map = JSObject::cast(object->IsJSObject() ? *object : 687 Map* map = JSObject::cast(object->IsJSObject() ? *object :
678 object->GetPrototype())->map(); 688 object->GetPrototype())->map();
679 689
680 // Update the stub cache. 690 // Update the stub cache.
681 StubCache::Set(*name, map, Code::cast(code)); 691 StubCache::Set(*name, map, Code::cast(code));
682 } 692 }
683 693
684 #ifdef DEBUG 694 #ifdef DEBUG
685 TraceIC(kind_ == Code::CALL_IC ? "CallIC" : "KeyedCallIC", 695 TraceIC(kind_ == Code::CALL_IC ? "CallIC" : "KeyedCallIC",
686 name, state, target(), in_loop ? " (in-loop)" : ""); 696 name, state, target(), in_loop ? " (in-loop)" : "");
687 #endif 697 #endif
688 } 698 }
689 699
690 700
691 Object* KeyedCallIC::LoadFunction(State state, 701 MaybeObject* KeyedCallIC::LoadFunction(State state,
692 Handle<Object> object, 702 Handle<Object> object,
693 Handle<Object> key) { 703 Handle<Object> key) {
694 if (key->IsSymbol()) { 704 if (key->IsSymbol()) {
695 return CallICBase::LoadFunction(state, object, Handle<String>::cast(key)); 705 return CallICBase::LoadFunction(state, object, Handle<String>::cast(key));
696 } 706 }
697 707
698 if (object->IsUndefined() || object->IsNull()) { 708 if (object->IsUndefined() || object->IsNull()) {
699 return TypeError("non_object_property_call", object, key); 709 return TypeError("non_object_property_call", object, key);
700 } 710 }
701 711
702 if (object->IsString() || object->IsNumber() || object->IsBoolean()) { 712 if (object->IsString() || object->IsNumber() || object->IsBoolean()) {
703 ReceiverToObject(object); 713 ReceiverToObject(object);
704 } 714 }
705 715
706 if (FLAG_use_ic && state != MEGAMORPHIC && !object->IsAccessCheckNeeded()) { 716 if (FLAG_use_ic && state != MEGAMORPHIC && !object->IsAccessCheckNeeded()) {
707 int argc = target()->arguments_count(); 717 int argc = target()->arguments_count();
708 InLoopFlag in_loop = target()->ic_in_loop(); 718 InLoopFlag in_loop = target()->ic_in_loop();
709 Object* code = StubCache::ComputeCallMegamorphic( 719 MaybeObject* maybe_code = StubCache::ComputeCallMegamorphic(
710 argc, in_loop, Code::KEYED_CALL_IC); 720 argc, in_loop, Code::KEYED_CALL_IC);
711 if (!code->IsFailure()) { 721 Object* code;
722 if (maybe_code->ToObject(&code)) {
712 set_target(Code::cast(code)); 723 set_target(Code::cast(code));
713 #ifdef DEBUG 724 #ifdef DEBUG
714 TraceIC( 725 TraceIC(
715 "KeyedCallIC", key, state, target(), in_loop ? " (in-loop)" : ""); 726 "KeyedCallIC", key, state, target(), in_loop ? " (in-loop)" : "");
716 #endif 727 #endif
717 } 728 }
718 } 729 }
719 Object* result = Runtime::GetObjectProperty(object, key); 730 Object* result;
731 { MaybeObject* maybe_result = Runtime::GetObjectProperty(object, key);
732 if (!maybe_result->ToObject(&result)) return maybe_result;
733 }
720 if (result->IsJSFunction()) return result; 734 if (result->IsJSFunction()) return result;
721 result = TryCallAsFunction(result); 735 result = TryCallAsFunction(result);
722 return result->IsJSFunction() ? 736 MaybeObject* answer = result;
723 result : TypeError("property_not_function", object, key); 737 if (!result->IsJSFunction()) {
738 answer = TypeError("property_not_function", object, key);
739 }
740 return answer;
724 } 741 }
725 742
726 743
727 #ifdef DEBUG 744 #ifdef DEBUG
728 #define TRACE_IC_NAMED(msg, name) \ 745 #define TRACE_IC_NAMED(msg, name) \
729 if (FLAG_trace_ic) PrintF(msg, *(name)->ToCString()) 746 if (FLAG_trace_ic) PrintF(msg, *(name)->ToCString())
730 #else 747 #else
731 #define TRACE_IC_NAMED(msg, name) 748 #define TRACE_IC_NAMED(msg, name)
732 #endif 749 #endif
733 750
734 751
735 Object* LoadIC::Load(State state, Handle<Object> object, Handle<String> name) { 752 MaybeObject* LoadIC::Load(State state,
753 Handle<Object> object,
754 Handle<String> name) {
736 // If the object is undefined or null it's illegal to try to get any 755 // If the object is undefined or null it's illegal to try to get any
737 // of its properties; throw a TypeError in that case. 756 // of its properties; throw a TypeError in that case.
738 if (object->IsUndefined() || object->IsNull()) { 757 if (object->IsUndefined() || object->IsNull()) {
739 return TypeError("non_object_property_load", object, name); 758 return TypeError("non_object_property_load", object, name);
740 } 759 }
741 760
742 if (FLAG_use_ic) { 761 if (FLAG_use_ic) {
743 // Use specialized code for getting the length of strings and 762 // Use specialized code for getting the length of strings and
744 // string wrapper objects. The length property of string wrapper 763 // string wrapper objects. The length property of string wrapper
745 // objects is read-only and therefore always returns the length of 764 // objects is read-only and therefore always returns the length of
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after
867 } 886 }
868 887
869 // Update inline cache and stub cache. 888 // Update inline cache and stub cache.
870 if (FLAG_use_ic) { 889 if (FLAG_use_ic) {
871 UpdateCaches(&lookup, state, object, name); 890 UpdateCaches(&lookup, state, object, name);
872 } 891 }
873 892
874 PropertyAttributes attr; 893 PropertyAttributes attr;
875 if (lookup.IsProperty() && lookup.type() == INTERCEPTOR) { 894 if (lookup.IsProperty() && lookup.type() == INTERCEPTOR) {
876 // Get the property. 895 // Get the property.
877 Object* result = object->GetProperty(*object, &lookup, *name, &attr); 896 Object* result;
878 if (result->IsFailure()) return result; 897 { MaybeObject* maybe_result =
898 object->GetProperty(*object, &lookup, *name, &attr);
899 if (!maybe_result->ToObject(&result)) return maybe_result;
900 }
879 // If the property is not present, check if we need to throw an 901 // If the property is not present, check if we need to throw an
880 // exception. 902 // exception.
881 if (attr == ABSENT && IsContextual(object)) { 903 if (attr == ABSENT && IsContextual(object)) {
882 return ReferenceError("not_defined", name); 904 return ReferenceError("not_defined", name);
883 } 905 }
884 return result; 906 return result;
885 } 907 }
886 908
887 // Get the property. 909 // Get the property.
888 return object->GetProperty(*object, &lookup, *name, &attr); 910 return object->GetProperty(*object, &lookup, *name, &attr);
889 } 911 }
890 912
891 913
892 void LoadIC::UpdateCaches(LookupResult* lookup, 914 void LoadIC::UpdateCaches(LookupResult* lookup,
893 State state, 915 State state,
894 Handle<Object> object, 916 Handle<Object> object,
895 Handle<String> name) { 917 Handle<String> name) {
896 // Bail out if the result is not cacheable. 918 // Bail out if the result is not cacheable.
897 if (!lookup->IsCacheable()) return; 919 if (!lookup->IsCacheable()) return;
898 920
899 // Loading properties from values is not common, so don't try to 921 // Loading properties from values is not common, so don't try to
900 // deal with non-JS objects here. 922 // deal with non-JS objects here.
901 if (!object->IsJSObject()) return; 923 if (!object->IsJSObject()) return;
902 Handle<JSObject> receiver = Handle<JSObject>::cast(object); 924 Handle<JSObject> receiver = Handle<JSObject>::cast(object);
903 925
904 if (HasNormalObjectsInPrototypeChain(lookup, *object)) return; 926 if (HasNormalObjectsInPrototypeChain(lookup, *object)) return;
905 927
906 // Compute the code stub for this load. 928 // Compute the code stub for this load.
907 Object* code = NULL; 929 MaybeObject* maybe_code = NULL;
930 Object* code;
908 if (state == UNINITIALIZED) { 931 if (state == UNINITIALIZED) {
909 // This is the first time we execute this inline cache. 932 // This is the first time we execute this inline cache.
910 // Set the target to the pre monomorphic stub to delay 933 // Set the target to the pre monomorphic stub to delay
911 // setting the monomorphic state. 934 // setting the monomorphic state.
912 code = pre_monomorphic_stub(); 935 maybe_code = pre_monomorphic_stub();
913 } else if (!lookup->IsProperty()) { 936 } else if (!lookup->IsProperty()) {
914 // Nonexistent property. The result is undefined. 937 // Nonexistent property. The result is undefined.
915 code = StubCache::ComputeLoadNonexistent(*name, *receiver); 938 maybe_code = StubCache::ComputeLoadNonexistent(*name, *receiver);
916 } else { 939 } else {
917 // Compute monomorphic stub. 940 // Compute monomorphic stub.
918 switch (lookup->type()) { 941 switch (lookup->type()) {
919 case FIELD: { 942 case FIELD: {
920 code = StubCache::ComputeLoadField(*name, *receiver, 943 maybe_code = StubCache::ComputeLoadField(*name, *receiver,
921 lookup->holder(), 944 lookup->holder(),
922 lookup->GetFieldIndex()); 945 lookup->GetFieldIndex());
923 break; 946 break;
924 } 947 }
925 case CONSTANT_FUNCTION: { 948 case CONSTANT_FUNCTION: {
926 Object* constant = lookup->GetConstantFunction(); 949 Object* constant = lookup->GetConstantFunction();
927 code = StubCache::ComputeLoadConstant(*name, *receiver, 950 maybe_code = StubCache::ComputeLoadConstant(*name, *receiver,
928 lookup->holder(), constant); 951 lookup->holder(), constant);
929 break; 952 break;
930 } 953 }
931 case NORMAL: { 954 case NORMAL: {
932 if (lookup->holder()->IsGlobalObject()) { 955 if (lookup->holder()->IsGlobalObject()) {
933 GlobalObject* global = GlobalObject::cast(lookup->holder()); 956 GlobalObject* global = GlobalObject::cast(lookup->holder());
934 JSGlobalPropertyCell* cell = 957 JSGlobalPropertyCell* cell =
935 JSGlobalPropertyCell::cast(global->GetPropertyCell(lookup)); 958 JSGlobalPropertyCell::cast(global->GetPropertyCell(lookup));
936 code = StubCache::ComputeLoadGlobal(*name, 959 maybe_code = StubCache::ComputeLoadGlobal(*name,
937 *receiver, 960 *receiver,
938 global, 961 global,
939 cell, 962 cell,
940 lookup->IsDontDelete()); 963 lookup->IsDontDelete());
941 } else { 964 } else {
942 // There is only one shared stub for loading normalized 965 // There is only one shared stub for loading normalized
943 // properties. It does not traverse the prototype chain, so the 966 // properties. It does not traverse the prototype chain, so the
944 // property must be found in the receiver for the stub to be 967 // property must be found in the receiver for the stub to be
945 // applicable. 968 // applicable.
946 if (lookup->holder() != *receiver) return; 969 if (lookup->holder() != *receiver) return;
947 code = StubCache::ComputeLoadNormal(); 970 maybe_code = StubCache::ComputeLoadNormal();
948 } 971 }
949 break; 972 break;
950 } 973 }
951 case CALLBACKS: { 974 case CALLBACKS: {
952 if (!lookup->GetCallbackObject()->IsAccessorInfo()) return; 975 if (!lookup->GetCallbackObject()->IsAccessorInfo()) return;
953 AccessorInfo* callback = 976 AccessorInfo* callback =
954 AccessorInfo::cast(lookup->GetCallbackObject()); 977 AccessorInfo::cast(lookup->GetCallbackObject());
955 if (v8::ToCData<Address>(callback->getter()) == 0) return; 978 if (v8::ToCData<Address>(callback->getter()) == 0) return;
956 code = StubCache::ComputeLoadCallback(*name, *receiver, 979 maybe_code = StubCache::ComputeLoadCallback(*name, *receiver,
957 lookup->holder(), callback); 980 lookup->holder(), callback);
958 break; 981 break;
959 } 982 }
960 case INTERCEPTOR: { 983 case INTERCEPTOR: {
961 ASSERT(HasInterceptorGetter(lookup->holder())); 984 ASSERT(HasInterceptorGetter(lookup->holder()));
962 code = StubCache::ComputeLoadInterceptor(*name, *receiver, 985 maybe_code = StubCache::ComputeLoadInterceptor(*name, *receiver,
963 lookup->holder()); 986 lookup->holder());
964 break; 987 break;
965 } 988 }
966 default: 989 default:
967 return; 990 return;
968 } 991 }
969 } 992 }
970 993
971 // If we're unable to compute the stub (not enough memory left), we 994 // If we're unable to compute the stub (not enough memory left), we
972 // simply avoid updating the caches. 995 // simply avoid updating the caches.
973 if (code == NULL || code->IsFailure()) return; 996 if (maybe_code == NULL || !maybe_code->ToObject(&code)) return;
974 997
975 // Patch the call site depending on the state of the cache. 998 // Patch the call site depending on the state of the cache.
976 if (state == UNINITIALIZED || state == PREMONOMORPHIC || 999 if (state == UNINITIALIZED || state == PREMONOMORPHIC ||
977 state == MONOMORPHIC_PROTOTYPE_FAILURE) { 1000 state == MONOMORPHIC_PROTOTYPE_FAILURE) {
978 set_target(Code::cast(code)); 1001 set_target(Code::cast(code));
979 } else if (state == MONOMORPHIC) { 1002 } else if (state == MONOMORPHIC) {
980 set_target(megamorphic_stub()); 1003 set_target(megamorphic_stub());
981 } else if (state == MEGAMORPHIC) { 1004 } else if (state == MEGAMORPHIC) {
982 // Cache code holding map should be consistent with 1005 // Cache code holding map should be consistent with
983 // GenerateMonomorphicCacheProbe. 1006 // GenerateMonomorphicCacheProbe.
984 Map* map = JSObject::cast(object->IsJSObject() ? *object : 1007 Map* map = JSObject::cast(object->IsJSObject() ? *object :
985 object->GetPrototype())->map(); 1008 object->GetPrototype())->map();
986 1009
987 StubCache::Set(*name, map, Code::cast(code)); 1010 StubCache::Set(*name, map, Code::cast(code));
988 } 1011 }
989 1012
990 #ifdef DEBUG 1013 #ifdef DEBUG
991 TraceIC("LoadIC", name, state, target()); 1014 TraceIC("LoadIC", name, state, target());
992 #endif 1015 #endif
993 } 1016 }
994 1017
995 1018
996 Object* KeyedLoadIC::Load(State state, 1019 MaybeObject* KeyedLoadIC::Load(State state,
997 Handle<Object> object, 1020 Handle<Object> object,
998 Handle<Object> key) { 1021 Handle<Object> key) {
999 if (key->IsSymbol()) { 1022 if (key->IsSymbol()) {
1000 Handle<String> name = Handle<String>::cast(key); 1023 Handle<String> name = Handle<String>::cast(key);
1001 1024
1002 // If the object is undefined or null it's illegal to try to get any 1025 // If the object is undefined or null it's illegal to try to get any
1003 // of its properties; throw a TypeError in that case. 1026 // of its properties; throw a TypeError in that case.
1004 if (object->IsUndefined() || object->IsNull()) { 1027 if (object->IsUndefined() || object->IsNull()) {
1005 return TypeError("non_object_property_load", object, name); 1028 return TypeError("non_object_property_load", object, name);
1006 } 1029 }
1007 1030
1008 if (FLAG_use_ic) { 1031 if (FLAG_use_ic) {
1009 // Use specialized code for getting the length of strings. 1032 // Use specialized code for getting the length of strings.
1010 if (object->IsString() && name->Equals(Heap::length_symbol())) { 1033 if (object->IsString() && name->Equals(Heap::length_symbol())) {
1011 Handle<String> string = Handle<String>::cast(object); 1034 Handle<String> string = Handle<String>::cast(object);
1012 Object* code = NULL; 1035 Object* code = NULL;
1013 code = StubCache::ComputeKeyedLoadStringLength(*name, *string); 1036 { MaybeObject* maybe_code =
1014 if (code->IsFailure()) return code; 1037 StubCache::ComputeKeyedLoadStringLength(*name, *string);
1038 if (!maybe_code->ToObject(&code)) return maybe_code;
1039 }
1015 set_target(Code::cast(code)); 1040 set_target(Code::cast(code));
1016 #ifdef DEBUG 1041 #ifdef DEBUG
1017 TraceIC("KeyedLoadIC", name, state, target()); 1042 TraceIC("KeyedLoadIC", name, state, target());
1018 #endif // DEBUG 1043 #endif // DEBUG
1019 return Smi::FromInt(string->length()); 1044 return Smi::FromInt(string->length());
1020 } 1045 }
1021 1046
1022 // Use specialized code for getting the length of arrays. 1047 // Use specialized code for getting the length of arrays.
1023 if (object->IsJSArray() && name->Equals(Heap::length_symbol())) { 1048 if (object->IsJSArray() && name->Equals(Heap::length_symbol())) {
1024 Handle<JSArray> array = Handle<JSArray>::cast(object); 1049 Handle<JSArray> array = Handle<JSArray>::cast(object);
1025 Object* code = StubCache::ComputeKeyedLoadArrayLength(*name, *array); 1050 Object* code;
1026 if (code->IsFailure()) return code; 1051 { MaybeObject* maybe_code =
1052 StubCache::ComputeKeyedLoadArrayLength(*name, *array);
1053 if (!maybe_code->ToObject(&code)) return maybe_code;
1054 }
1027 set_target(Code::cast(code)); 1055 set_target(Code::cast(code));
1028 #ifdef DEBUG 1056 #ifdef DEBUG
1029 TraceIC("KeyedLoadIC", name, state, target()); 1057 TraceIC("KeyedLoadIC", name, state, target());
1030 #endif // DEBUG 1058 #endif // DEBUG
1031 return JSArray::cast(*object)->length(); 1059 return JSArray::cast(*object)->length();
1032 } 1060 }
1033 1061
1034 // Use specialized code for getting prototype of functions. 1062 // Use specialized code for getting prototype of functions.
1035 if (object->IsJSFunction() && name->Equals(Heap::prototype_symbol()) && 1063 if (object->IsJSFunction() && name->Equals(Heap::prototype_symbol()) &&
1036 JSFunction::cast(*object)->should_have_prototype()) { 1064 JSFunction::cast(*object)->should_have_prototype()) {
1037 Handle<JSFunction> function = Handle<JSFunction>::cast(object); 1065 Handle<JSFunction> function = Handle<JSFunction>::cast(object);
1038 Object* code = 1066 Object* code;
1039 StubCache::ComputeKeyedLoadFunctionPrototype(*name, *function); 1067 { MaybeObject* maybe_code =
1040 if (code->IsFailure()) return code; 1068 StubCache::ComputeKeyedLoadFunctionPrototype(*name, *function);
1069 if (!maybe_code->ToObject(&code)) return maybe_code;
1070 }
1041 set_target(Code::cast(code)); 1071 set_target(Code::cast(code));
1042 #ifdef DEBUG 1072 #ifdef DEBUG
1043 TraceIC("KeyedLoadIC", name, state, target()); 1073 TraceIC("KeyedLoadIC", name, state, target());
1044 #endif // DEBUG 1074 #endif // DEBUG
1045 return Accessors::FunctionGetPrototype(*object, 0); 1075 return Accessors::FunctionGetPrototype(*object, 0);
1046 } 1076 }
1047 } 1077 }
1048 1078
1049 // Check if the name is trivially convertible to an index and get 1079 // Check if the name is trivially convertible to an index and get
1050 // the element or char if so. 1080 // the element or char if so.
(...skipping 16 matching lines...) Expand all
1067 } 1097 }
1068 } 1098 }
1069 1099
1070 if (FLAG_use_ic) { 1100 if (FLAG_use_ic) {
1071 UpdateCaches(&lookup, state, object, name); 1101 UpdateCaches(&lookup, state, object, name);
1072 } 1102 }
1073 1103
1074 PropertyAttributes attr; 1104 PropertyAttributes attr;
1075 if (lookup.IsProperty() && lookup.type() == INTERCEPTOR) { 1105 if (lookup.IsProperty() && lookup.type() == INTERCEPTOR) {
1076 // Get the property. 1106 // Get the property.
1077 Object* result = object->GetProperty(*object, &lookup, *name, &attr); 1107 Object* result;
1078 if (result->IsFailure()) return result; 1108 { MaybeObject* maybe_result =
1109 object->GetProperty(*object, &lookup, *name, &attr);
1110 if (!maybe_result->ToObject(&result)) return maybe_result;
1111 }
1079 // If the property is not present, check if we need to throw an 1112 // If the property is not present, check if we need to throw an
1080 // exception. 1113 // exception.
1081 if (attr == ABSENT && IsContextual(object)) { 1114 if (attr == ABSENT && IsContextual(object)) {
1082 return ReferenceError("not_defined", name); 1115 return ReferenceError("not_defined", name);
1083 } 1116 }
1084 return result; 1117 return result;
1085 } 1118 }
1086 1119
1087 return object->GetProperty(*object, &lookup, *name, &attr); 1120 return object->GetProperty(*object, &lookup, *name, &attr);
1088 } 1121 }
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
1126 Handle<Object> object, Handle<String> name) { 1159 Handle<Object> object, Handle<String> name) {
1127 // Bail out if we didn't find a result. 1160 // Bail out if we didn't find a result.
1128 if (!lookup->IsProperty() || !lookup->IsCacheable()) return; 1161 if (!lookup->IsProperty() || !lookup->IsCacheable()) return;
1129 1162
1130 if (!object->IsJSObject()) return; 1163 if (!object->IsJSObject()) return;
1131 Handle<JSObject> receiver = Handle<JSObject>::cast(object); 1164 Handle<JSObject> receiver = Handle<JSObject>::cast(object);
1132 1165
1133 if (HasNormalObjectsInPrototypeChain(lookup, *object)) return; 1166 if (HasNormalObjectsInPrototypeChain(lookup, *object)) return;
1134 1167
1135 // Compute the code stub for this load. 1168 // Compute the code stub for this load.
1136 Object* code = NULL; 1169 MaybeObject* maybe_code = NULL;
1170 Object* code;
1137 1171
1138 if (state == UNINITIALIZED) { 1172 if (state == UNINITIALIZED) {
1139 // This is the first time we execute this inline cache. 1173 // This is the first time we execute this inline cache.
1140 // Set the target to the pre monomorphic stub to delay 1174 // Set the target to the pre monomorphic stub to delay
1141 // setting the monomorphic state. 1175 // setting the monomorphic state.
1142 code = pre_monomorphic_stub(); 1176 maybe_code = pre_monomorphic_stub();
1143 } else { 1177 } else {
1144 // Compute a monomorphic stub. 1178 // Compute a monomorphic stub.
1145 switch (lookup->type()) { 1179 switch (lookup->type()) {
1146 case FIELD: { 1180 case FIELD: {
1147 code = StubCache::ComputeKeyedLoadField(*name, *receiver, 1181 maybe_code = StubCache::ComputeKeyedLoadField(*name, *receiver,
1148 lookup->holder(), 1182 lookup->holder(),
1149 lookup->GetFieldIndex()); 1183 lookup->GetFieldIndex());
1150 break; 1184 break;
1151 } 1185 }
1152 case CONSTANT_FUNCTION: { 1186 case CONSTANT_FUNCTION: {
1153 Object* constant = lookup->GetConstantFunction(); 1187 Object* constant = lookup->GetConstantFunction();
1154 code = StubCache::ComputeKeyedLoadConstant(*name, *receiver, 1188 maybe_code = StubCache::ComputeKeyedLoadConstant(*name,
1155 lookup->holder(), constant); 1189 *receiver,
1190 lookup->holder(),
1191 constant);
1156 break; 1192 break;
1157 } 1193 }
1158 case CALLBACKS: { 1194 case CALLBACKS: {
1159 if (!lookup->GetCallbackObject()->IsAccessorInfo()) return; 1195 if (!lookup->GetCallbackObject()->IsAccessorInfo()) return;
1160 AccessorInfo* callback = 1196 AccessorInfo* callback =
1161 AccessorInfo::cast(lookup->GetCallbackObject()); 1197 AccessorInfo::cast(lookup->GetCallbackObject());
1162 if (v8::ToCData<Address>(callback->getter()) == 0) return; 1198 if (v8::ToCData<Address>(callback->getter()) == 0) return;
1163 code = StubCache::ComputeKeyedLoadCallback(*name, *receiver, 1199 maybe_code = StubCache::ComputeKeyedLoadCallback(*name,
1164 lookup->holder(), callback); 1200 *receiver,
1201 lookup->holder(),
1202 callback);
1165 break; 1203 break;
1166 } 1204 }
1167 case INTERCEPTOR: { 1205 case INTERCEPTOR: {
1168 ASSERT(HasInterceptorGetter(lookup->holder())); 1206 ASSERT(HasInterceptorGetter(lookup->holder()));
1169 code = StubCache::ComputeKeyedLoadInterceptor(*name, *receiver, 1207 maybe_code = StubCache::ComputeKeyedLoadInterceptor(*name, *receiver,
1170 lookup->holder()); 1208 lookup->holder());
1171 break; 1209 break;
1172 } 1210 }
1173 default: { 1211 default: {
1174 // Always rewrite to the generic case so that we do not 1212 // Always rewrite to the generic case so that we do not
1175 // repeatedly try to rewrite. 1213 // repeatedly try to rewrite.
1176 code = generic_stub(); 1214 maybe_code = generic_stub();
1177 break; 1215 break;
1178 } 1216 }
1179 } 1217 }
1180 } 1218 }
1181 1219
1182 // If we're unable to compute the stub (not enough memory left), we 1220 // If we're unable to compute the stub (not enough memory left), we
1183 // simply avoid updating the caches. 1221 // simply avoid updating the caches.
1184 if (code == NULL || code->IsFailure()) return; 1222 if (maybe_code == NULL || !maybe_code->ToObject(&code)) return;
1185 1223
1186 // Patch the call site depending on the state of the cache. Make 1224 // Patch the call site depending on the state of the cache. Make
1187 // sure to always rewrite from monomorphic to megamorphic. 1225 // sure to always rewrite from monomorphic to megamorphic.
1188 ASSERT(state != MONOMORPHIC_PROTOTYPE_FAILURE); 1226 ASSERT(state != MONOMORPHIC_PROTOTYPE_FAILURE);
1189 if (state == UNINITIALIZED || state == PREMONOMORPHIC) { 1227 if (state == UNINITIALIZED || state == PREMONOMORPHIC) {
1190 set_target(Code::cast(code)); 1228 set_target(Code::cast(code));
1191 } else if (state == MONOMORPHIC) { 1229 } else if (state == MONOMORPHIC) {
1192 set_target(megamorphic_stub()); 1230 set_target(megamorphic_stub());
1193 } 1231 }
1194 1232
(...skipping 27 matching lines...) Expand all
1222 if (object->GetNamedInterceptor()->setter()->IsUndefined()) { 1260 if (object->GetNamedInterceptor()->setter()->IsUndefined()) {
1223 object->LocalLookupRealNamedProperty(name, lookup); 1261 object->LocalLookupRealNamedProperty(name, lookup);
1224 return StoreICableLookup(lookup); 1262 return StoreICableLookup(lookup);
1225 } 1263 }
1226 } 1264 }
1227 1265
1228 return true; 1266 return true;
1229 } 1267 }
1230 1268
1231 1269
1232 Object* StoreIC::Store(State state, 1270 MaybeObject* StoreIC::Store(State state,
1233 Handle<Object> object, 1271 Handle<Object> object,
1234 Handle<String> name, 1272 Handle<String> name,
1235 Handle<Object> value) { 1273 Handle<Object> value) {
1236 // If the object is undefined or null it's illegal to try to set any 1274 // If the object is undefined or null it's illegal to try to set any
1237 // properties on it; throw a TypeError in that case. 1275 // properties on it; throw a TypeError in that case.
1238 if (object->IsUndefined() || object->IsNull()) { 1276 if (object->IsUndefined() || object->IsNull()) {
1239 return TypeError("non_object_property_store", object, name); 1277 return TypeError("non_object_property_store", object, name);
1240 } 1278 }
1241 1279
1242 // Ignore stores where the receiver is not a JSObject. 1280 // Ignore stores where the receiver is not a JSObject.
1243 if (!object->IsJSObject()) return *value; 1281 if (!object->IsJSObject()) return *value;
1244 Handle<JSObject> receiver = Handle<JSObject>::cast(object); 1282 Handle<JSObject> receiver = Handle<JSObject>::cast(object);
1245 1283
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
1338 ASSERT(StoreICableLookup(lookup)); 1376 ASSERT(StoreICableLookup(lookup));
1339 1377
1340 // If the property has a non-field type allowing map transitions 1378 // If the property has a non-field type allowing map transitions
1341 // where there is extra room in the object, we leave the IC in its 1379 // where there is extra room in the object, we leave the IC in its
1342 // current state. 1380 // current state.
1343 PropertyType type = lookup->type(); 1381 PropertyType type = lookup->type();
1344 1382
1345 // Compute the code stub for this store; used for rewriting to 1383 // Compute the code stub for this store; used for rewriting to
1346 // monomorphic state and making sure that the code stub is in the 1384 // monomorphic state and making sure that the code stub is in the
1347 // stub cache. 1385 // stub cache.
1386 MaybeObject* maybe_code = NULL;
1348 Object* code = NULL; 1387 Object* code = NULL;
1349 switch (type) { 1388 switch (type) {
1350 case FIELD: { 1389 case FIELD: {
1351 code = StubCache::ComputeStoreField(*name, *receiver, 1390 maybe_code = StubCache::ComputeStoreField(*name, *receiver,
1352 lookup->GetFieldIndex()); 1391 lookup->GetFieldIndex());
1353 break; 1392 break;
1354 } 1393 }
1355 case MAP_TRANSITION: { 1394 case MAP_TRANSITION: {
1356 if (lookup->GetAttributes() != NONE) return; 1395 if (lookup->GetAttributes() != NONE) return;
1357 HandleScope scope; 1396 HandleScope scope;
1358 ASSERT(type == MAP_TRANSITION); 1397 ASSERT(type == MAP_TRANSITION);
1359 Handle<Map> transition(lookup->GetTransitionMap()); 1398 Handle<Map> transition(lookup->GetTransitionMap());
1360 int index = transition->PropertyIndexFor(*name); 1399 int index = transition->PropertyIndexFor(*name);
1361 code = StubCache::ComputeStoreField(*name, *receiver, index, *transition); 1400 maybe_code = StubCache::ComputeStoreField(*name, *receiver,
1401 index, *transition);
1362 break; 1402 break;
1363 } 1403 }
1364 case NORMAL: { 1404 case NORMAL: {
1365 if (receiver->IsGlobalObject()) { 1405 if (receiver->IsGlobalObject()) {
1366 // The stub generated for the global object picks the value directly 1406 // The stub generated for the global object picks the value directly
1367 // from the property cell. So the property must be directly on the 1407 // from the property cell. So the property must be directly on the
1368 // global object. 1408 // global object.
1369 Handle<GlobalObject> global = Handle<GlobalObject>::cast(receiver); 1409 Handle<GlobalObject> global = Handle<GlobalObject>::cast(receiver);
1370 JSGlobalPropertyCell* cell = 1410 JSGlobalPropertyCell* cell =
1371 JSGlobalPropertyCell::cast(global->GetPropertyCell(lookup)); 1411 JSGlobalPropertyCell::cast(global->GetPropertyCell(lookup));
1372 code = StubCache::ComputeStoreGlobal(*name, *global, cell); 1412 maybe_code = StubCache::ComputeStoreGlobal(*name, *global, cell);
1373 } else { 1413 } else {
1374 if (lookup->holder() != *receiver) return; 1414 if (lookup->holder() != *receiver) return;
1375 code = StubCache::ComputeStoreNormal(); 1415 maybe_code = StubCache::ComputeStoreNormal();
1376 } 1416 }
1377 break; 1417 break;
1378 } 1418 }
1379 case CALLBACKS: { 1419 case CALLBACKS: {
1380 if (!lookup->GetCallbackObject()->IsAccessorInfo()) return; 1420 if (!lookup->GetCallbackObject()->IsAccessorInfo()) return;
1381 AccessorInfo* callback = AccessorInfo::cast(lookup->GetCallbackObject()); 1421 AccessorInfo* callback = AccessorInfo::cast(lookup->GetCallbackObject());
1382 if (v8::ToCData<Address>(callback->setter()) == 0) return; 1422 if (v8::ToCData<Address>(callback->setter()) == 0) return;
1383 code = StubCache::ComputeStoreCallback(*name, *receiver, callback); 1423 maybe_code = StubCache::ComputeStoreCallback(*name, *receiver, callback);
1384 break; 1424 break;
1385 } 1425 }
1386 case INTERCEPTOR: { 1426 case INTERCEPTOR: {
1387 ASSERT(!receiver->GetNamedInterceptor()->setter()->IsUndefined()); 1427 ASSERT(!receiver->GetNamedInterceptor()->setter()->IsUndefined());
1388 code = StubCache::ComputeStoreInterceptor(*name, *receiver); 1428 maybe_code = StubCache::ComputeStoreInterceptor(*name, *receiver);
1389 break; 1429 break;
1390 } 1430 }
1391 default: 1431 default:
1392 return; 1432 return;
1393 } 1433 }
1394 1434
1395 // If we're unable to compute the stub (not enough memory left), we 1435 // If we're unable to compute the stub (not enough memory left), we
1396 // simply avoid updating the caches. 1436 // simply avoid updating the caches.
1397 if (code == NULL || code->IsFailure()) return; 1437 if (maybe_code == NULL || !maybe_code->ToObject(&code)) return;
1398 1438
1399 // Patch the call site depending on the state of the cache. 1439 // Patch the call site depending on the state of the cache.
1400 if (state == UNINITIALIZED || state == MONOMORPHIC_PROTOTYPE_FAILURE) { 1440 if (state == UNINITIALIZED || state == MONOMORPHIC_PROTOTYPE_FAILURE) {
1401 set_target(Code::cast(code)); 1441 set_target(Code::cast(code));
1402 } else if (state == MONOMORPHIC) { 1442 } else if (state == MONOMORPHIC) {
1403 // Only move to megamorphic if the target changes. 1443 // Only move to megamorphic if the target changes.
1404 if (target() != Code::cast(code)) set_target(megamorphic_stub()); 1444 if (target() != Code::cast(code)) set_target(megamorphic_stub());
1405 } else if (state == MEGAMORPHIC) { 1445 } else if (state == MEGAMORPHIC) {
1406 // Update the stub cache. 1446 // Update the stub cache.
1407 StubCache::Set(*name, receiver->map(), Code::cast(code)); 1447 StubCache::Set(*name, receiver->map(), Code::cast(code));
1408 } 1448 }
1409 1449
1410 #ifdef DEBUG 1450 #ifdef DEBUG
1411 TraceIC("StoreIC", name, state, target()); 1451 TraceIC("StoreIC", name, state, target());
1412 #endif 1452 #endif
1413 } 1453 }
1414 1454
1415 1455
1416 Object* KeyedStoreIC::Store(State state, 1456 MaybeObject* KeyedStoreIC::Store(State state,
1417 Handle<Object> object, 1457 Handle<Object> object,
1418 Handle<Object> key, 1458 Handle<Object> key,
1419 Handle<Object> value) { 1459 Handle<Object> value) {
1420 if (key->IsSymbol()) { 1460 if (key->IsSymbol()) {
1421 Handle<String> name = Handle<String>::cast(key); 1461 Handle<String> name = Handle<String>::cast(key);
1422 1462
1423 // If the object is undefined or null it's illegal to try to set any 1463 // If the object is undefined or null it's illegal to try to set any
1424 // properties on it; throw a TypeError in that case. 1464 // properties on it; throw a TypeError in that case.
1425 if (object->IsUndefined() || object->IsNull()) { 1465 if (object->IsUndefined() || object->IsNull()) {
1426 return TypeError("non_object_property_store", object, name); 1466 return TypeError("non_object_property_store", object, name);
1427 } 1467 }
1428 1468
1429 // Ignore stores where the receiver is not a JSObject. 1469 // Ignore stores where the receiver is not a JSObject.
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
1489 if (lookup->IsReadOnly()) return; 1529 if (lookup->IsReadOnly()) return;
1490 1530
1491 // If the property has a non-field type allowing map transitions 1531 // If the property has a non-field type allowing map transitions
1492 // where there is extra room in the object, we leave the IC in its 1532 // where there is extra room in the object, we leave the IC in its
1493 // current state. 1533 // current state.
1494 PropertyType type = lookup->type(); 1534 PropertyType type = lookup->type();
1495 1535
1496 // Compute the code stub for this store; used for rewriting to 1536 // Compute the code stub for this store; used for rewriting to
1497 // monomorphic state and making sure that the code stub is in the 1537 // monomorphic state and making sure that the code stub is in the
1498 // stub cache. 1538 // stub cache.
1539 MaybeObject* maybe_code = NULL;
1499 Object* code = NULL; 1540 Object* code = NULL;
1500 1541
1501 switch (type) { 1542 switch (type) {
1502 case FIELD: { 1543 case FIELD: {
1503 code = StubCache::ComputeKeyedStoreField(*name, *receiver, 1544 maybe_code = StubCache::ComputeKeyedStoreField(*name, *receiver,
1504 lookup->GetFieldIndex()); 1545 lookup->GetFieldIndex());
1505 break; 1546 break;
1506 } 1547 }
1507 case MAP_TRANSITION: { 1548 case MAP_TRANSITION: {
1508 if (lookup->GetAttributes() == NONE) { 1549 if (lookup->GetAttributes() == NONE) {
1509 HandleScope scope; 1550 HandleScope scope;
1510 ASSERT(type == MAP_TRANSITION); 1551 ASSERT(type == MAP_TRANSITION);
1511 Handle<Map> transition(lookup->GetTransitionMap()); 1552 Handle<Map> transition(lookup->GetTransitionMap());
1512 int index = transition->PropertyIndexFor(*name); 1553 int index = transition->PropertyIndexFor(*name);
1513 code = StubCache::ComputeKeyedStoreField(*name, *receiver, 1554 maybe_code = StubCache::ComputeKeyedStoreField(*name, *receiver,
1514 index, *transition); 1555 index, *transition);
1515 break; 1556 break;
1516 } 1557 }
1517 // fall through. 1558 // fall through.
1518 } 1559 }
1519 default: { 1560 default: {
1520 // Always rewrite to the generic case so that we do not 1561 // Always rewrite to the generic case so that we do not
1521 // repeatedly try to rewrite. 1562 // repeatedly try to rewrite.
1522 code = generic_stub(); 1563 maybe_code = generic_stub();
1523 break; 1564 break;
1524 } 1565 }
1525 } 1566 }
1526 1567
1527 // If we're unable to compute the stub (not enough memory left), we 1568 // If we're unable to compute the stub (not enough memory left), we
1528 // simply avoid updating the caches. 1569 // simply avoid updating the caches.
1529 if (code == NULL || code->IsFailure()) return; 1570 if (maybe_code == NULL || !maybe_code->ToObject(&code)) return;
1530 1571
1531 // Patch the call site depending on the state of the cache. Make 1572 // Patch the call site depending on the state of the cache. Make
1532 // sure to always rewrite from monomorphic to megamorphic. 1573 // sure to always rewrite from monomorphic to megamorphic.
1533 ASSERT(state != MONOMORPHIC_PROTOTYPE_FAILURE); 1574 ASSERT(state != MONOMORPHIC_PROTOTYPE_FAILURE);
1534 if (state == UNINITIALIZED || state == PREMONOMORPHIC) { 1575 if (state == UNINITIALIZED || state == PREMONOMORPHIC) {
1535 set_target(Code::cast(code)); 1576 set_target(Code::cast(code));
1536 } else if (state == MONOMORPHIC) { 1577 } else if (state == MONOMORPHIC) {
1537 set_target(megamorphic_stub()); 1578 set_target(megamorphic_stub());
1538 } 1579 }
1539 1580
(...skipping 15 matching lines...) Expand all
1555 if (in_loop == IN_LOOP) { 1596 if (in_loop == IN_LOOP) {
1556 CompileLazyInLoop(function_handle, CLEAR_EXCEPTION); 1597 CompileLazyInLoop(function_handle, CLEAR_EXCEPTION);
1557 } else { 1598 } else {
1558 CompileLazy(function_handle, CLEAR_EXCEPTION); 1599 CompileLazy(function_handle, CLEAR_EXCEPTION);
1559 } 1600 }
1560 return *function_handle; 1601 return *function_handle;
1561 } 1602 }
1562 1603
1563 1604
1564 // Used from ic-<arch>.cc. 1605 // Used from ic-<arch>.cc.
1565 Object* CallIC_Miss(Arguments args) { 1606 MUST_USE_RESULT MaybeObject* CallIC_Miss(Arguments args) {
1566 NoHandleAllocation na; 1607 NoHandleAllocation na;
1567 ASSERT(args.length() == 2); 1608 ASSERT(args.length() == 2);
1568 CallIC ic; 1609 CallIC ic;
1569 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); 1610 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]);
1570 Object* result = 1611 Object* result;
1571 ic.LoadFunction(state, args.at<Object>(0), args.at<String>(1)); 1612 { MaybeObject* maybe_result =
1613 ic.LoadFunction(state, args.at<Object>(0), args.at<String>(1));
1614 if (!maybe_result->ToObject(&result)) return maybe_result;
1615 }
1572 1616
1573 // The first time the inline cache is updated may be the first time the 1617 // The first time the inline cache is updated may be the first time the
1574 // function it references gets called. If the function was lazily compiled 1618 // function it references gets called. If the function was lazily compiled
1575 // then the first call will trigger a compilation. We check for this case 1619 // then the first call will trigger a compilation. We check for this case
1576 // and we do the compilation immediately, instead of waiting for the stub 1620 // and we do the compilation immediately, instead of waiting for the stub
1577 // currently attached to the JSFunction object to trigger compilation. We 1621 // currently attached to the JSFunction object to trigger compilation. We
1578 // do this in the case where we know that the inline cache is inside a loop, 1622 // do this in the case where we know that the inline cache is inside a loop,
1579 // because then we know that we want to optimize the function. 1623 // because then we know that we want to optimize the function.
1580 if (!result->IsJSFunction() || JSFunction::cast(result)->is_compiled()) { 1624 if (!result->IsJSFunction() || JSFunction::cast(result)->is_compiled()) {
1581 return result; 1625 return result;
1582 } 1626 }
1583 return CompileFunction(JSFunction::cast(result), ic.target()->ic_in_loop()); 1627 return CompileFunction(JSFunction::cast(result), ic.target()->ic_in_loop());
1584 } 1628 }
1585 1629
1586 1630
1587 // Used from ic-<arch>.cc. 1631 // Used from ic-<arch>.cc.
1588 Object* KeyedCallIC_Miss(Arguments args) { 1632 MUST_USE_RESULT MaybeObject* KeyedCallIC_Miss(Arguments args) {
1589 NoHandleAllocation na; 1633 NoHandleAllocation na;
1590 ASSERT(args.length() == 2); 1634 ASSERT(args.length() == 2);
1591 KeyedCallIC ic; 1635 KeyedCallIC ic;
1592 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); 1636 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]);
1593 Object* result = 1637 Object* result;
1638 { MaybeObject* maybe_result =
1594 ic.LoadFunction(state, args.at<Object>(0), args.at<Object>(1)); 1639 ic.LoadFunction(state, args.at<Object>(0), args.at<Object>(1));
1640 if (!maybe_result->ToObject(&result)) return maybe_result;
1641 }
1595 1642
1596 if (!result->IsJSFunction() || JSFunction::cast(result)->is_compiled()) { 1643 if (!result->IsJSFunction() || JSFunction::cast(result)->is_compiled()) {
1597 return result; 1644 return result;
1598 } 1645 }
1599 return CompileFunction(JSFunction::cast(result), ic.target()->ic_in_loop()); 1646 return CompileFunction(JSFunction::cast(result), ic.target()->ic_in_loop());
1600 } 1647 }
1601 1648
1602 1649
1603 // Used from ic-<arch>.cc. 1650 // Used from ic-<arch>.cc.
1604 Object* LoadIC_Miss(Arguments args) { 1651 MUST_USE_RESULT MaybeObject* LoadIC_Miss(Arguments args) {
1605 NoHandleAllocation na; 1652 NoHandleAllocation na;
1606 ASSERT(args.length() == 2); 1653 ASSERT(args.length() == 2);
1607 LoadIC ic; 1654 LoadIC ic;
1608 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); 1655 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]);
1609 return ic.Load(state, args.at<Object>(0), args.at<String>(1)); 1656 return ic.Load(state, args.at<Object>(0), args.at<String>(1));
1610 } 1657 }
1611 1658
1612 1659
1613 // Used from ic-<arch>.cc 1660 // Used from ic-<arch>.cc
1614 Object* KeyedLoadIC_Miss(Arguments args) { 1661 MUST_USE_RESULT MaybeObject* KeyedLoadIC_Miss(Arguments args) {
1615 NoHandleAllocation na; 1662 NoHandleAllocation na;
1616 ASSERT(args.length() == 2); 1663 ASSERT(args.length() == 2);
1617 KeyedLoadIC ic; 1664 KeyedLoadIC ic;
1618 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); 1665 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]);
1619 return ic.Load(state, args.at<Object>(0), args.at<Object>(1)); 1666 return ic.Load(state, args.at<Object>(0), args.at<Object>(1));
1620 } 1667 }
1621 1668
1622 1669
1623 // Used from ic-<arch>.cc. 1670 // Used from ic-<arch>.cc.
1624 Object* StoreIC_Miss(Arguments args) { 1671 MUST_USE_RESULT MaybeObject* StoreIC_Miss(Arguments args) {
1625 NoHandleAllocation na; 1672 NoHandleAllocation na;
1626 ASSERT(args.length() == 3); 1673 ASSERT(args.length() == 3);
1627 StoreIC ic; 1674 StoreIC ic;
1628 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); 1675 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]);
1629 return ic.Store(state, args.at<Object>(0), args.at<String>(1), 1676 return ic.Store(state, args.at<Object>(0), args.at<String>(1),
1630 args.at<Object>(2)); 1677 args.at<Object>(2));
1631 } 1678 }
1632 1679
1633 1680
1634 Object* StoreIC_ArrayLength(Arguments args) { 1681 MUST_USE_RESULT MaybeObject* StoreIC_ArrayLength(Arguments args) {
1635 NoHandleAllocation nha; 1682 NoHandleAllocation nha;
1636 1683
1637 ASSERT(args.length() == 2); 1684 ASSERT(args.length() == 2);
1638 JSObject* receiver = JSObject::cast(args[0]); 1685 JSObject* receiver = JSObject::cast(args[0]);
1639 Object* len = args[1]; 1686 Object* len = args[1];
1640 1687
1641 Object* result = receiver->SetElementsLength(len); 1688 // The generated code should filter out non-Smis before we get here.
1642 if (result->IsFailure()) return result; 1689 ASSERT(len->IsSmi());
1690
1691 Object* result;
1692 { MaybeObject* maybe_result = receiver->SetElementsLength(len);
1693 if (!maybe_result->ToObject(&result)) return maybe_result;
1694 }
1643 return len; 1695 return len;
1644 } 1696 }
1645 1697
1646 1698
1647 // Extend storage is called in a store inline cache when 1699 // Extend storage is called in a store inline cache when
1648 // it is necessary to extend the properties array of a 1700 // it is necessary to extend the properties array of a
1649 // JSObject. 1701 // JSObject.
1650 Object* SharedStoreIC_ExtendStorage(Arguments args) { 1702 MUST_USE_RESULT MaybeObject* SharedStoreIC_ExtendStorage(Arguments args) {
1651 NoHandleAllocation na; 1703 NoHandleAllocation na;
1652 ASSERT(args.length() == 3); 1704 ASSERT(args.length() == 3);
1653 1705
1654 // Convert the parameters 1706 // Convert the parameters
1655 JSObject* object = JSObject::cast(args[0]); 1707 JSObject* object = JSObject::cast(args[0]);
1656 Map* transition = Map::cast(args[1]); 1708 Map* transition = Map::cast(args[1]);
1657 Object* value = args[2]; 1709 Object* value = args[2];
1658 1710
1659 // Check the object has run out out property space. 1711 // Check the object has run out out property space.
1660 ASSERT(object->HasFastProperties()); 1712 ASSERT(object->HasFastProperties());
1661 ASSERT(object->map()->unused_property_fields() == 0); 1713 ASSERT(object->map()->unused_property_fields() == 0);
1662 1714
1663 // Expand the properties array. 1715 // Expand the properties array.
1664 FixedArray* old_storage = object->properties(); 1716 FixedArray* old_storage = object->properties();
1665 int new_unused = transition->unused_property_fields(); 1717 int new_unused = transition->unused_property_fields();
1666 int new_size = old_storage->length() + new_unused + 1; 1718 int new_size = old_storage->length() + new_unused + 1;
1667 Object* result = old_storage->CopySize(new_size); 1719 Object* result;
1668 if (result->IsFailure()) return result; 1720 { MaybeObject* maybe_result = old_storage->CopySize(new_size);
1721 if (!maybe_result->ToObject(&result)) return maybe_result;
1722 }
1669 FixedArray* new_storage = FixedArray::cast(result); 1723 FixedArray* new_storage = FixedArray::cast(result);
1670 new_storage->set(old_storage->length(), value); 1724 new_storage->set(old_storage->length(), value);
1671 1725
1672 // Set the new property value and do the map transition. 1726 // Set the new property value and do the map transition.
1673 object->set_properties(new_storage); 1727 object->set_properties(new_storage);
1674 object->set_map(transition); 1728 object->set_map(transition);
1675 1729
1676 // Return the stored value. 1730 // Return the stored value.
1677 return value; 1731 return value;
1678 } 1732 }
1679 1733
1680 1734
1681 // Used from ic-<arch>.cc. 1735 // Used from ic-<arch>.cc.
1682 Object* KeyedStoreIC_Miss(Arguments args) { 1736 MUST_USE_RESULT MaybeObject* KeyedStoreIC_Miss(Arguments args) {
1683 NoHandleAllocation na; 1737 NoHandleAllocation na;
1684 ASSERT(args.length() == 3); 1738 ASSERT(args.length() == 3);
1685 KeyedStoreIC ic; 1739 KeyedStoreIC ic;
1686 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); 1740 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]);
1687 return ic.Store(state, args.at<Object>(0), args.at<Object>(1), 1741 return ic.Store(state, args.at<Object>(0), args.at<Object>(1),
1688 args.at<Object>(2)); 1742 args.at<Object>(2));
1689 } 1743 }
1690 1744
1691 1745
1692 void BinaryOpIC::patch(Code* code) { 1746 void BinaryOpIC::patch(Code* code) {
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
1737 } 1791 }
1738 1792
1739 return GENERIC; 1793 return GENERIC;
1740 } 1794 }
1741 1795
1742 1796
1743 // defined in codegen-<arch>.cc 1797 // defined in codegen-<arch>.cc
1744 Handle<Code> GetBinaryOpStub(int key, BinaryOpIC::TypeInfo type_info); 1798 Handle<Code> GetBinaryOpStub(int key, BinaryOpIC::TypeInfo type_info);
1745 1799
1746 1800
1747 Object* BinaryOp_Patch(Arguments args) { 1801 MUST_USE_RESULT MaybeObject* BinaryOp_Patch(Arguments args) {
1748 ASSERT(args.length() == 5); 1802 ASSERT(args.length() == 5);
1749 1803
1750 Handle<Object> left = args.at<Object>(0); 1804 Handle<Object> left = args.at<Object>(0);
1751 Handle<Object> right = args.at<Object>(1); 1805 Handle<Object> right = args.at<Object>(1);
1752 int key = Smi::cast(args[2])->value(); 1806 int key = Smi::cast(args[2])->value();
1753 Token::Value op = static_cast<Token::Value>(Smi::cast(args[3])->value()); 1807 Token::Value op = static_cast<Token::Value>(Smi::cast(args[3])->value());
1754 #ifdef DEBUG 1808 #ifdef DEBUG
1755 BinaryOpIC::TypeInfo prev_type_info = 1809 BinaryOpIC::TypeInfo prev_type_info =
1756 static_cast<BinaryOpIC::TypeInfo>(Smi::cast(args[4])->value()); 1810 static_cast<BinaryOpIC::TypeInfo>(Smi::cast(args[4])->value());
1757 #endif // DEBUG 1811 #endif // DEBUG
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
1838 #undef ADDR 1892 #undef ADDR
1839 }; 1893 };
1840 1894
1841 1895
1842 Address IC::AddressFromUtilityId(IC::UtilityId id) { 1896 Address IC::AddressFromUtilityId(IC::UtilityId id) {
1843 return IC_utilities[id]; 1897 return IC_utilities[id];
1844 } 1898 }
1845 1899
1846 1900
1847 } } // namespace v8::internal 1901 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/ic.h ('k') | src/liveedit.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698