| 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 312 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 323 static void LookupForRead(Object* object, | 323 static void LookupForRead(Object* object, |
| 324 String* name, | 324 String* name, |
| 325 LookupResult* lookup) { | 325 LookupResult* lookup) { |
| 326 AssertNoAllocation no_gc; // pointers must stay valid | 326 AssertNoAllocation no_gc; // pointers must stay valid |
| 327 | 327 |
| 328 // Skip all the objects with named interceptors, but | 328 // Skip all the objects with named interceptors, but |
| 329 // without actual getter. | 329 // without actual getter. |
| 330 while (true) { | 330 while (true) { |
| 331 object->Lookup(name, lookup); | 331 object->Lookup(name, lookup); |
| 332 // Besides normal conditions (property not found or it's not | 332 // Besides normal conditions (property not found or it's not |
| 333 // an interceptor), bail out of lookup is not cacheable: we won't | 333 // an interceptor), bail out if lookup is not cacheable: we won't |
| 334 // be able to IC it anyway and regular lookup should work fine. | 334 // be able to IC it anyway and regular lookup should work fine. |
| 335 if (lookup->IsNotFound() || lookup->type() != INTERCEPTOR || | 335 if (!lookup->IsFound() |
| 336 !lookup->IsCacheable()) { | 336 || (lookup->type() != INTERCEPTOR) |
| 337 || !lookup->IsCacheable()) { |
| 337 return; | 338 return; |
| 338 } | 339 } |
| 339 | 340 |
| 340 JSObject* holder = lookup->holder(); | 341 JSObject* holder = lookup->holder(); |
| 341 if (HasInterceptorGetter(holder)) { | 342 if (HasInterceptorGetter(holder)) { |
| 342 return; | 343 return; |
| 343 } | 344 } |
| 344 | 345 |
| 345 holder->LocalLookupRealNamedProperty(name, lookup); | 346 holder->LocalLookupRealNamedProperty(name, lookup); |
| 346 if (lookup->IsValid()) { | 347 if (lookup->IsProperty()) { |
| 347 ASSERT(lookup->type() != INTERCEPTOR); | 348 ASSERT(lookup->type() != INTERCEPTOR); |
| 348 return; | 349 return; |
| 349 } | 350 } |
| 350 | 351 |
| 351 Object* proto = holder->GetPrototype(); | 352 Object* proto = holder->GetPrototype(); |
| 352 if (proto->IsNull()) { | 353 if (proto->IsNull()) { |
| 353 lookup->NotFound(); | 354 lookup->NotFound(); |
| 354 return; | 355 return; |
| 355 } | 356 } |
| 356 | 357 |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 415 result = TryCallAsFunction(result); | 416 result = TryCallAsFunction(result); |
| 416 if (result->IsJSFunction()) return result; | 417 if (result->IsJSFunction()) return result; |
| 417 | 418 |
| 418 // Otherwise, it will fail in the lookup step. | 419 // Otherwise, it will fail in the lookup step. |
| 419 } | 420 } |
| 420 | 421 |
| 421 // Lookup the property in the object. | 422 // Lookup the property in the object. |
| 422 LookupResult lookup; | 423 LookupResult lookup; |
| 423 LookupForRead(*object, *name, &lookup); | 424 LookupForRead(*object, *name, &lookup); |
| 424 | 425 |
| 425 if (!lookup.IsValid()) { | 426 if (!lookup.IsProperty()) { |
| 426 // If the object does not have the requested property, check which | 427 // If the object does not have the requested property, check which |
| 427 // exception we need to throw. | 428 // exception we need to throw. |
| 428 if (IsContextual(object)) { | 429 if (IsContextual(object)) { |
| 429 return ReferenceError("not_defined", name); | 430 return ReferenceError("not_defined", name); |
| 430 } | 431 } |
| 431 return TypeError("undefined_method", object, name); | 432 return TypeError("undefined_method", object, name); |
| 432 } | 433 } |
| 433 | 434 |
| 434 // Lookup is valid: Update inline cache and stub cache. | 435 // Lookup is valid: Update inline cache and stub cache. |
| 435 if (FLAG_use_ic) { | 436 if (FLAG_use_ic) { |
| (...skipping 12 matching lines...) Expand all Loading... |
| 448 return ReferenceError("not_defined", name); | 449 return ReferenceError("not_defined", name); |
| 449 } | 450 } |
| 450 return TypeError("undefined_method", object, name); | 451 return TypeError("undefined_method", object, name); |
| 451 } | 452 } |
| 452 } | 453 } |
| 453 | 454 |
| 454 ASSERT(result != Heap::the_hole_value()); | 455 ASSERT(result != Heap::the_hole_value()); |
| 455 | 456 |
| 456 if (result->IsJSFunction()) { | 457 if (result->IsJSFunction()) { |
| 457 // Check if there is an optimized (builtin) version of the function. | 458 // Check if there is an optimized (builtin) version of the function. |
| 458 // Ignored this will degrade performance for Array.prototype.{push,pop}. | 459 // Ignored this will degrade performance for some Array functions. |
| 459 // Please note we only return the optimized function iff | 460 // Please note we only return the optimized function iff |
| 460 // the JSObject has FastElements. | 461 // the JSObject has FastElements. |
| 461 if (object->IsJSObject() && JSObject::cast(*object)->HasFastElements()) { | 462 if (object->IsJSObject() && JSObject::cast(*object)->HasFastElements()) { |
| 462 Object* opt = Top::LookupSpecialFunction(JSObject::cast(*object), | 463 Object* opt = Top::LookupSpecialFunction(JSObject::cast(*object), |
| 463 lookup.holder(), | 464 lookup.holder(), |
| 464 JSFunction::cast(result)); | 465 JSFunction::cast(result)); |
| 465 if (opt->IsJSFunction()) return opt; | 466 if (opt->IsJSFunction()) return opt; |
| 466 } | 467 } |
| 467 | 468 |
| 468 #ifdef ENABLE_DEBUGGER_SUPPORT | 469 #ifdef ENABLE_DEBUGGER_SUPPORT |
| (...skipping 16 matching lines...) Expand all Loading... |
| 485 return result->IsJSFunction() ? | 486 return result->IsJSFunction() ? |
| 486 result : TypeError("property_not_function", object, name); | 487 result : TypeError("property_not_function", object, name); |
| 487 } | 488 } |
| 488 | 489 |
| 489 | 490 |
| 490 void CallIC::UpdateCaches(LookupResult* lookup, | 491 void CallIC::UpdateCaches(LookupResult* lookup, |
| 491 State state, | 492 State state, |
| 492 Handle<Object> object, | 493 Handle<Object> object, |
| 493 Handle<String> name) { | 494 Handle<String> name) { |
| 494 // Bail out if we didn't find a result. | 495 // Bail out if we didn't find a result. |
| 495 if (!lookup->IsValid() || !lookup->IsCacheable()) return; | 496 if (!lookup->IsProperty() || !lookup->IsCacheable()) return; |
| 496 | 497 |
| 497 // Compute the number of arguments. | 498 // Compute the number of arguments. |
| 498 int argc = target()->arguments_count(); | 499 int argc = target()->arguments_count(); |
| 499 InLoopFlag in_loop = target()->ic_in_loop(); | 500 InLoopFlag in_loop = target()->ic_in_loop(); |
| 500 Object* code = NULL; | 501 Object* code = NULL; |
| 501 | 502 |
| 502 if (state == UNINITIALIZED) { | 503 if (state == UNINITIALIZED) { |
| 503 // This is the first time we execute this inline cache. | 504 // This is the first time we execute this inline cache. |
| 504 // Set the target to the pre monomorphic stub to delay | 505 // Set the target to the pre monomorphic stub to delay |
| 505 // setting the monomorphic state. | 506 // setting the monomorphic state. |
| (...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 634 | 635 |
| 635 // Check if the name is trivially convertible to an index and get | 636 // Check if the name is trivially convertible to an index and get |
| 636 // the element if so. | 637 // the element if so. |
| 637 uint32_t index; | 638 uint32_t index; |
| 638 if (name->AsArrayIndex(&index)) return object->GetElement(index); | 639 if (name->AsArrayIndex(&index)) return object->GetElement(index); |
| 639 | 640 |
| 640 // Named lookup in the object. | 641 // Named lookup in the object. |
| 641 LookupResult lookup; | 642 LookupResult lookup; |
| 642 LookupForRead(*object, *name, &lookup); | 643 LookupForRead(*object, *name, &lookup); |
| 643 | 644 |
| 644 // If lookup is invalid, check if we need to throw an exception. | 645 // If we did not find a property, check if we need to throw an exception. |
| 645 if (!lookup.IsValid()) { | 646 if (!lookup.IsProperty()) { |
| 646 if (FLAG_strict || IsContextual(object)) { | 647 if (FLAG_strict || IsContextual(object)) { |
| 647 return ReferenceError("not_defined", name); | 648 return ReferenceError("not_defined", name); |
| 648 } | 649 } |
| 649 LOG(SuspectReadEvent(*name, *object)); | 650 LOG(SuspectReadEvent(*name, *object)); |
| 650 } | 651 } |
| 651 | 652 |
| 652 bool can_be_inlined = | 653 bool can_be_inlined = |
| 653 FLAG_use_ic && | 654 FLAG_use_ic && |
| 654 state == PREMONOMORPHIC && | 655 state == PREMONOMORPHIC && |
| 655 lookup.IsValid() && | 656 lookup.IsProperty() && |
| 656 lookup.IsCacheable() && | 657 lookup.IsCacheable() && |
| 657 lookup.holder() == *object && | 658 lookup.holder() == *object && |
| 658 lookup.type() == FIELD && | 659 lookup.type() == FIELD && |
| 659 !object->IsAccessCheckNeeded(); | 660 !object->IsAccessCheckNeeded(); |
| 660 | 661 |
| 661 if (can_be_inlined) { | 662 if (can_be_inlined) { |
| 662 Map* map = lookup.holder()->map(); | 663 Map* map = lookup.holder()->map(); |
| 663 // Property's index in the properties array. If negative we have | 664 // Property's index in the properties array. If negative we have |
| 664 // an inobject property. | 665 // an inobject property. |
| 665 int index = lookup.GetFieldIndex() - map->inobject_properties(); | 666 int index = lookup.GetFieldIndex() - map->inobject_properties(); |
| 666 if (index < 0) { | 667 if (index < 0) { |
| 667 // Index is an offset from the end of the object. | 668 // Index is an offset from the end of the object. |
| 668 int offset = map->instance_size() + (index * kPointerSize); | 669 int offset = map->instance_size() + (index * kPointerSize); |
| 669 if (PatchInlinedLoad(address(), map, offset)) { | 670 if (PatchInlinedLoad(address(), map, offset)) { |
| 670 set_target(megamorphic_stub()); | 671 set_target(megamorphic_stub()); |
| 671 return lookup.holder()->FastPropertyAt(lookup.GetFieldIndex()); | 672 return lookup.holder()->FastPropertyAt(lookup.GetFieldIndex()); |
| 672 } | 673 } |
| 673 } | 674 } |
| 674 } | 675 } |
| 675 | 676 |
| 676 // Update inline cache and stub cache. | 677 // Update inline cache and stub cache. |
| 677 if (FLAG_use_ic) { | 678 if (FLAG_use_ic) { |
| 678 UpdateCaches(&lookup, state, object, name); | 679 UpdateCaches(&lookup, state, object, name); |
| 679 } | 680 } |
| 680 | 681 |
| 681 PropertyAttributes attr; | 682 PropertyAttributes attr; |
| 682 if (lookup.IsValid() && lookup.type() == INTERCEPTOR) { | 683 if (lookup.IsProperty() && lookup.type() == INTERCEPTOR) { |
| 683 // Get the property. | 684 // Get the property. |
| 684 Object* result = object->GetProperty(*object, &lookup, *name, &attr); | 685 Object* result = object->GetProperty(*object, &lookup, *name, &attr); |
| 685 if (result->IsFailure()) return result; | 686 if (result->IsFailure()) return result; |
| 686 // If the property is not present, check if we need to throw an | 687 // If the property is not present, check if we need to throw an |
| 687 // exception. | 688 // exception. |
| 688 if (attr == ABSENT && IsContextual(object)) { | 689 if (attr == ABSENT && IsContextual(object)) { |
| 689 return ReferenceError("not_defined", name); | 690 return ReferenceError("not_defined", name); |
| 690 } | 691 } |
| 691 return result; | 692 return result; |
| 692 } | 693 } |
| 693 | 694 |
| 694 // Get the property. | 695 // Get the property. |
| 695 return object->GetProperty(*object, &lookup, *name, &attr); | 696 return object->GetProperty(*object, &lookup, *name, &attr); |
| 696 } | 697 } |
| 697 | 698 |
| 698 | 699 |
| 699 void LoadIC::UpdateCaches(LookupResult* lookup, | 700 void LoadIC::UpdateCaches(LookupResult* lookup, |
| 700 State state, | 701 State state, |
| 701 Handle<Object> object, | 702 Handle<Object> object, |
| 702 Handle<String> name) { | 703 Handle<String> name) { |
| 703 // Bail out if we didn't find a result. | 704 // Bail out if we didn't find a result. |
| 704 if (!lookup->IsValid() || !lookup->IsCacheable()) return; | 705 if (!lookup->IsProperty() || !lookup->IsCacheable()) return; |
| 705 | 706 |
| 706 // Loading properties from values is not common, so don't try to | 707 // Loading properties from values is not common, so don't try to |
| 707 // deal with non-JS objects here. | 708 // deal with non-JS objects here. |
| 708 if (!object->IsJSObject()) return; | 709 if (!object->IsJSObject()) return; |
| 709 Handle<JSObject> receiver = Handle<JSObject>::cast(object); | 710 Handle<JSObject> receiver = Handle<JSObject>::cast(object); |
| 710 | 711 |
| 711 // Compute the code stub for this load. | 712 // Compute the code stub for this load. |
| 712 Object* code = NULL; | 713 Object* code = NULL; |
| 713 if (state == UNINITIALIZED) { | 714 if (state == UNINITIALIZED) { |
| 714 // This is the first time we execute this inline cache. | 715 // This is the first time we execute this inline cache. |
| (...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 847 HandleScope scope; | 848 HandleScope scope; |
| 848 // Rewrite to the generic keyed load stub. | 849 // Rewrite to the generic keyed load stub. |
| 849 if (FLAG_use_ic) set_target(generic_stub()); | 850 if (FLAG_use_ic) set_target(generic_stub()); |
| 850 return Runtime::GetElementOrCharAt(object, index); | 851 return Runtime::GetElementOrCharAt(object, index); |
| 851 } | 852 } |
| 852 | 853 |
| 853 // Named lookup. | 854 // Named lookup. |
| 854 LookupResult lookup; | 855 LookupResult lookup; |
| 855 LookupForRead(*object, *name, &lookup); | 856 LookupForRead(*object, *name, &lookup); |
| 856 | 857 |
| 857 // If lookup is invalid, check if we need to throw an exception. | 858 // If we did not find a property, check if we need to throw an exception. |
| 858 if (!lookup.IsValid()) { | 859 if (!lookup.IsProperty()) { |
| 859 if (FLAG_strict || IsContextual(object)) { | 860 if (FLAG_strict || IsContextual(object)) { |
| 860 return ReferenceError("not_defined", name); | 861 return ReferenceError("not_defined", name); |
| 861 } | 862 } |
| 862 } | 863 } |
| 863 | 864 |
| 864 if (FLAG_use_ic) { | 865 if (FLAG_use_ic) { |
| 865 UpdateCaches(&lookup, state, object, name); | 866 UpdateCaches(&lookup, state, object, name); |
| 866 } | 867 } |
| 867 | 868 |
| 868 PropertyAttributes attr; | 869 PropertyAttributes attr; |
| 869 if (lookup.IsValid() && lookup.type() == INTERCEPTOR) { | 870 if (lookup.IsProperty() && lookup.type() == INTERCEPTOR) { |
| 870 // Get the property. | 871 // Get the property. |
| 871 Object* result = object->GetProperty(*object, &lookup, *name, &attr); | 872 Object* result = object->GetProperty(*object, &lookup, *name, &attr); |
| 872 if (result->IsFailure()) return result; | 873 if (result->IsFailure()) return result; |
| 873 // If the property is not present, check if we need to throw an | 874 // If the property is not present, check if we need to throw an |
| 874 // exception. | 875 // exception. |
| 875 if (attr == ABSENT && IsContextual(object)) { | 876 if (attr == ABSENT && IsContextual(object)) { |
| 876 return ReferenceError("not_defined", name); | 877 return ReferenceError("not_defined", name); |
| 877 } | 878 } |
| 878 return result; | 879 return result; |
| 879 } | 880 } |
| 880 | 881 |
| 881 return object->GetProperty(*object, &lookup, *name, &attr); | 882 return object->GetProperty(*object, &lookup, *name, &attr); |
| 882 } | 883 } |
| 883 | 884 |
| 884 // Do not use ICs for objects that require access checks (including | 885 // Do not use ICs for objects that require access checks (including |
| 885 // the global object). | 886 // the global object). |
| 886 bool use_ic = FLAG_use_ic && !object->IsAccessCheckNeeded(); | 887 bool use_ic = FLAG_use_ic && !object->IsAccessCheckNeeded(); |
| 887 | 888 |
| 888 if (use_ic) { | 889 if (use_ic) { |
| 889 Code* stub = generic_stub(); | 890 Code* stub = generic_stub(); |
| 890 if (object->IsString() && key->IsNumber()) { | 891 if (object->IsString() && key->IsNumber()) { |
| 891 stub = string_stub(); | 892 stub = string_stub(); |
| 892 } else if (object->IsJSObject()) { | 893 } else if (object->IsJSObject()) { |
| 893 Handle<JSObject> receiver = Handle<JSObject>::cast(object); | 894 Handle<JSObject> receiver = Handle<JSObject>::cast(object); |
| 894 if (receiver->HasExternalArrayElements()) { | 895 if (receiver->HasExternalArrayElements()) { |
| 895 stub = external_array_stub(receiver->GetElementsKind()); | 896 stub = external_array_stub(receiver->GetElementsKind()); |
| 897 } else if (receiver->HasIndexedInterceptor()) { |
| 898 stub = indexed_interceptor_stub(); |
| 896 } | 899 } |
| 897 } | 900 } |
| 898 set_target(stub); | 901 set_target(stub); |
| 899 // For JSObjects that are not value wrappers and that do not have | 902 // For JSObjects that are not value wrappers and that do not have |
| 900 // indexed interceptors, we initialize the inlined fast case (if | 903 // indexed interceptors, we initialize the inlined fast case (if |
| 901 // present) by patching the inlined map check. | 904 // present) by patching the inlined map check. |
| 902 if (object->IsJSObject() && | 905 if (object->IsJSObject() && |
| 903 !object->IsJSValue() && | 906 !object->IsJSValue() && |
| 904 !JSObject::cast(*object)->HasIndexedInterceptor()) { | 907 !JSObject::cast(*object)->HasIndexedInterceptor()) { |
| 905 Map* map = JSObject::cast(*object)->map(); | 908 Map* map = JSObject::cast(*object)->map(); |
| 906 PatchInlinedLoad(address(), map); | 909 PatchInlinedLoad(address(), map); |
| 907 } | 910 } |
| 908 } | 911 } |
| 909 | 912 |
| 910 // Get the property. | 913 // Get the property. |
| 911 return Runtime::GetObjectProperty(object, key); | 914 return Runtime::GetObjectProperty(object, key); |
| 912 } | 915 } |
| 913 | 916 |
| 914 | 917 |
| 915 void KeyedLoadIC::UpdateCaches(LookupResult* lookup, State state, | 918 void KeyedLoadIC::UpdateCaches(LookupResult* lookup, State state, |
| 916 Handle<Object> object, Handle<String> name) { | 919 Handle<Object> object, Handle<String> name) { |
| 917 // Bail out if we didn't find a result. | 920 // Bail out if we didn't find a result. |
| 918 if (!lookup->IsValid() || !lookup->IsCacheable()) return; | 921 if (!lookup->IsProperty() || !lookup->IsCacheable()) return; |
| 919 | 922 |
| 920 if (!object->IsJSObject()) return; | 923 if (!object->IsJSObject()) return; |
| 921 Handle<JSObject> receiver = Handle<JSObject>::cast(object); | 924 Handle<JSObject> receiver = Handle<JSObject>::cast(object); |
| 922 | 925 |
| 923 // Compute the code stub for this load. | 926 // Compute the code stub for this load. |
| 924 Object* code = NULL; | 927 Object* code = NULL; |
| 925 | 928 |
| 926 if (state == UNINITIALIZED) { | 929 if (state == UNINITIALIZED) { |
| 927 // This is the first time we execute this inline cache. | 930 // This is the first time we execute this inline cache. |
| 928 // Set the target to the pre monomorphic stub to delay | 931 // Set the target to the pre monomorphic stub to delay |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 981 } | 984 } |
| 982 | 985 |
| 983 #ifdef DEBUG | 986 #ifdef DEBUG |
| 984 TraceIC("KeyedLoadIC", name, state, target()); | 987 TraceIC("KeyedLoadIC", name, state, target()); |
| 985 #endif | 988 #endif |
| 986 } | 989 } |
| 987 | 990 |
| 988 | 991 |
| 989 static bool StoreICableLookup(LookupResult* lookup) { | 992 static bool StoreICableLookup(LookupResult* lookup) { |
| 990 // Bail out if we didn't find a result. | 993 // Bail out if we didn't find a result. |
| 991 if (!lookup->IsValid() || !lookup->IsCacheable()) return false; | 994 if (!lookup->IsPropertyOrTransition() || !lookup->IsCacheable()) return false; |
| 992 | 995 |
| 993 // If the property is read-only, we leave the IC in its current | 996 // If the property is read-only, we leave the IC in its current |
| 994 // state. | 997 // state. |
| 995 if (lookup->IsReadOnly()) return false; | 998 if (lookup->IsReadOnly()) return false; |
| 996 | 999 |
| 997 return true; | 1000 return true; |
| 998 } | 1001 } |
| 999 | 1002 |
| 1000 | 1003 |
| 1001 static bool LookupForWrite(JSObject* object, | 1004 static bool LookupForWrite(JSObject* object, |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1033 | 1036 |
| 1034 // Check if the given name is an array index. | 1037 // Check if the given name is an array index. |
| 1035 uint32_t index; | 1038 uint32_t index; |
| 1036 if (name->AsArrayIndex(&index)) { | 1039 if (name->AsArrayIndex(&index)) { |
| 1037 HandleScope scope; | 1040 HandleScope scope; |
| 1038 Handle<Object> result = SetElement(receiver, index, value); | 1041 Handle<Object> result = SetElement(receiver, index, value); |
| 1039 if (result.is_null()) return Failure::Exception(); | 1042 if (result.is_null()) return Failure::Exception(); |
| 1040 return *value; | 1043 return *value; |
| 1041 } | 1044 } |
| 1042 | 1045 |
| 1046 |
| 1047 // Use specialized code for setting the length of arrays. |
| 1048 if (receiver->IsJSArray() |
| 1049 && name->Equals(Heap::length_symbol()) |
| 1050 && receiver->AllowsSetElementsLength()) { |
| 1051 #ifdef DEBUG |
| 1052 if (FLAG_trace_ic) PrintF("[StoreIC : +#length /array]\n"); |
| 1053 #endif |
| 1054 Code* target = Builtins::builtin(Builtins::StoreIC_ArrayLength); |
| 1055 set_target(target); |
| 1056 StubCache::Set(*name, HeapObject::cast(*object)->map(), target); |
| 1057 return receiver->SetProperty(*name, *value, NONE); |
| 1058 } |
| 1059 |
| 1043 // Lookup the property locally in the receiver. | 1060 // Lookup the property locally in the receiver. |
| 1044 if (FLAG_use_ic && !receiver->IsJSGlobalProxy()) { | 1061 if (FLAG_use_ic && !receiver->IsJSGlobalProxy()) { |
| 1045 LookupResult lookup; | 1062 LookupResult lookup; |
| 1046 if (LookupForWrite(*receiver, *name, &lookup)) { | 1063 if (LookupForWrite(*receiver, *name, &lookup)) { |
| 1047 UpdateCaches(&lookup, state, receiver, name, value); | 1064 UpdateCaches(&lookup, state, receiver, name, value); |
| 1048 } | 1065 } |
| 1049 } | 1066 } |
| 1050 | 1067 |
| 1051 // Set the property. | 1068 // Set the property. |
| 1052 return receiver->SetProperty(*name, *value, NONE); | 1069 return receiver->SetProperty(*name, *value, NONE); |
| (...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1196 | 1213 |
| 1197 void KeyedStoreIC::UpdateCaches(LookupResult* lookup, | 1214 void KeyedStoreIC::UpdateCaches(LookupResult* lookup, |
| 1198 State state, | 1215 State state, |
| 1199 Handle<JSObject> receiver, | 1216 Handle<JSObject> receiver, |
| 1200 Handle<String> name, | 1217 Handle<String> name, |
| 1201 Handle<Object> value) { | 1218 Handle<Object> value) { |
| 1202 // Skip JSGlobalProxy. | 1219 // Skip JSGlobalProxy. |
| 1203 if (receiver->IsJSGlobalProxy()) return; | 1220 if (receiver->IsJSGlobalProxy()) return; |
| 1204 | 1221 |
| 1205 // Bail out if we didn't find a result. | 1222 // Bail out if we didn't find a result. |
| 1206 if (!lookup->IsValid() || !lookup->IsCacheable()) return; | 1223 if (!lookup->IsPropertyOrTransition() || !lookup->IsCacheable()) return; |
| 1207 | 1224 |
| 1208 // If the property is read-only, we leave the IC in its current | 1225 // If the property is read-only, we leave the IC in its current |
| 1209 // state. | 1226 // state. |
| 1210 if (lookup->IsReadOnly()) return; | 1227 if (lookup->IsReadOnly()) return; |
| 1211 | 1228 |
| 1212 // If the property has a non-field type allowing map transitions | 1229 // If the property has a non-field type allowing map transitions |
| 1213 // where there is extra room in the object, we leave the IC in its | 1230 // where there is extra room in the object, we leave the IC in its |
| 1214 // current state. | 1231 // current state. |
| 1215 PropertyType type = lookup->type(); | 1232 PropertyType type = lookup->type(); |
| 1216 | 1233 |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1304 // Used from ic_<arch>.cc. | 1321 // Used from ic_<arch>.cc. |
| 1305 Object* LoadIC_Miss(Arguments args) { | 1322 Object* LoadIC_Miss(Arguments args) { |
| 1306 NoHandleAllocation na; | 1323 NoHandleAllocation na; |
| 1307 ASSERT(args.length() == 2); | 1324 ASSERT(args.length() == 2); |
| 1308 LoadIC ic; | 1325 LoadIC ic; |
| 1309 IC::State state = IC::StateFrom(ic.target(), args[0]); | 1326 IC::State state = IC::StateFrom(ic.target(), args[0]); |
| 1310 return ic.Load(state, args.at<Object>(0), args.at<String>(1)); | 1327 return ic.Load(state, args.at<Object>(0), args.at<String>(1)); |
| 1311 } | 1328 } |
| 1312 | 1329 |
| 1313 | 1330 |
| 1314 void LoadIC::GenerateInitialize(MacroAssembler* masm) { | |
| 1315 Generate(masm, ExternalReference(IC_Utility(kLoadIC_Miss))); | |
| 1316 } | |
| 1317 | |
| 1318 | |
| 1319 void LoadIC::GeneratePreMonomorphic(MacroAssembler* masm) { | |
| 1320 Generate(masm, ExternalReference(IC_Utility(kLoadIC_Miss))); | |
| 1321 } | |
| 1322 | |
| 1323 | |
| 1324 // Used from ic_<arch>.cc | 1331 // Used from ic_<arch>.cc |
| 1325 Object* KeyedLoadIC_Miss(Arguments args) { | 1332 Object* KeyedLoadIC_Miss(Arguments args) { |
| 1326 NoHandleAllocation na; | 1333 NoHandleAllocation na; |
| 1327 ASSERT(args.length() == 2); | 1334 ASSERT(args.length() == 2); |
| 1328 KeyedLoadIC ic; | 1335 KeyedLoadIC ic; |
| 1329 IC::State state = IC::StateFrom(ic.target(), args[0]); | 1336 IC::State state = IC::StateFrom(ic.target(), args[0]); |
| 1330 return ic.Load(state, args.at<Object>(0), args.at<Object>(1)); | 1337 return ic.Load(state, args.at<Object>(0), args.at<Object>(1)); |
| 1331 } | 1338 } |
| 1332 | 1339 |
| 1333 | 1340 |
| 1334 void KeyedLoadIC::GenerateInitialize(MacroAssembler* masm) { | |
| 1335 Generate(masm, ExternalReference(IC_Utility(kKeyedLoadIC_Miss))); | |
| 1336 } | |
| 1337 | |
| 1338 | |
| 1339 void KeyedLoadIC::GeneratePreMonomorphic(MacroAssembler* masm) { | |
| 1340 Generate(masm, ExternalReference(IC_Utility(kKeyedLoadIC_Miss))); | |
| 1341 } | |
| 1342 | |
| 1343 | |
| 1344 // Used from ic_<arch>.cc. | 1341 // Used from ic_<arch>.cc. |
| 1345 Object* StoreIC_Miss(Arguments args) { | 1342 Object* StoreIC_Miss(Arguments args) { |
| 1346 NoHandleAllocation na; | 1343 NoHandleAllocation na; |
| 1347 ASSERT(args.length() == 3); | 1344 ASSERT(args.length() == 3); |
| 1348 StoreIC ic; | 1345 StoreIC ic; |
| 1349 IC::State state = IC::StateFrom(ic.target(), args[0]); | 1346 IC::State state = IC::StateFrom(ic.target(), args[0]); |
| 1350 return ic.Store(state, args.at<Object>(0), args.at<String>(1), | 1347 return ic.Store(state, args.at<Object>(0), args.at<String>(1), |
| 1351 args.at<Object>(2)); | 1348 args.at<Object>(2)); |
| 1352 } | 1349 } |
| 1353 | 1350 |
| 1354 | 1351 |
| 1352 Object* StoreIC_ArrayLength(Arguments args) { |
| 1353 NoHandleAllocation nha; |
| 1354 |
| 1355 ASSERT(args.length() == 2); |
| 1356 JSObject* receiver = JSObject::cast(args[0]); |
| 1357 Object* len = args[1]; |
| 1358 |
| 1359 return receiver->SetElementsLength(len); |
| 1360 } |
| 1361 |
| 1362 |
| 1355 // Extend storage is called in a store inline cache when | 1363 // Extend storage is called in a store inline cache when |
| 1356 // it is necessary to extend the properties array of a | 1364 // it is necessary to extend the properties array of a |
| 1357 // JSObject. | 1365 // JSObject. |
| 1358 Object* SharedStoreIC_ExtendStorage(Arguments args) { | 1366 Object* SharedStoreIC_ExtendStorage(Arguments args) { |
| 1359 NoHandleAllocation na; | 1367 NoHandleAllocation na; |
| 1360 ASSERT(args.length() == 3); | 1368 ASSERT(args.length() == 3); |
| 1361 | 1369 |
| 1362 // Convert the parameters | 1370 // Convert the parameters |
| 1363 JSObject* object = JSObject::cast(args[0]); | 1371 JSObject* object = JSObject::cast(args[0]); |
| 1364 Map* transition = Map::cast(args[1]); | 1372 Map* transition = Map::cast(args[1]); |
| (...skipping 25 matching lines...) Expand all Loading... |
| 1390 Object* KeyedStoreIC_Miss(Arguments args) { | 1398 Object* KeyedStoreIC_Miss(Arguments args) { |
| 1391 NoHandleAllocation na; | 1399 NoHandleAllocation na; |
| 1392 ASSERT(args.length() == 3); | 1400 ASSERT(args.length() == 3); |
| 1393 KeyedStoreIC ic; | 1401 KeyedStoreIC ic; |
| 1394 IC::State state = IC::StateFrom(ic.target(), args[0]); | 1402 IC::State state = IC::StateFrom(ic.target(), args[0]); |
| 1395 return ic.Store(state, args.at<Object>(0), args.at<Object>(1), | 1403 return ic.Store(state, args.at<Object>(0), args.at<Object>(1), |
| 1396 args.at<Object>(2)); | 1404 args.at<Object>(2)); |
| 1397 } | 1405 } |
| 1398 | 1406 |
| 1399 | 1407 |
| 1400 void KeyedStoreIC::GenerateInitialize(MacroAssembler* masm) { | |
| 1401 Generate(masm, ExternalReference(IC_Utility(kKeyedStoreIC_Miss))); | |
| 1402 } | |
| 1403 | |
| 1404 | |
| 1405 void KeyedStoreIC::GenerateMiss(MacroAssembler* masm) { | |
| 1406 Generate(masm, ExternalReference(IC_Utility(kKeyedStoreIC_Miss))); | |
| 1407 } | |
| 1408 | |
| 1409 | |
| 1410 static Address IC_utilities[] = { | 1408 static Address IC_utilities[] = { |
| 1411 #define ADDR(name) FUNCTION_ADDR(name), | 1409 #define ADDR(name) FUNCTION_ADDR(name), |
| 1412 IC_UTIL_LIST(ADDR) | 1410 IC_UTIL_LIST(ADDR) |
| 1413 NULL | 1411 NULL |
| 1414 #undef ADDR | 1412 #undef ADDR |
| 1415 }; | 1413 }; |
| 1416 | 1414 |
| 1417 | 1415 |
| 1418 Address IC::AddressFromUtilityId(IC::UtilityId id) { | 1416 Address IC::AddressFromUtilityId(IC::UtilityId id) { |
| 1419 return IC_utilities[id]; | 1417 return IC_utilities[id]; |
| 1420 } | 1418 } |
| 1421 | 1419 |
| 1422 | 1420 |
| 1423 } } // namespace v8::internal | 1421 } } // namespace v8::internal |
| OLD | NEW |