OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |