| 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 |