OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 531 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
542 int index = frame->ComputeExpressionsCount() - (argc + 1); | 542 int index = frame->ComputeExpressionsCount() - (argc + 1); |
543 frame->SetExpression(index, *isolate()->factory()->ToObject(object)); | 543 frame->SetExpression(index, *isolate()->factory()->ToObject(object)); |
544 } | 544 } |
545 } | 545 } |
546 | 546 |
547 | 547 |
548 MaybeObject* CallICBase::LoadFunction(State state, | 548 MaybeObject* CallICBase::LoadFunction(State state, |
549 Code::ExtraICState extra_ic_state, | 549 Code::ExtraICState extra_ic_state, |
550 Handle<Object> object, | 550 Handle<Object> object, |
551 Handle<String> name) { | 551 Handle<String> name) { |
552 bool use_ic = FLAG_use_ic; | |
553 if (object->IsJSObject()) { | 552 if (object->IsJSObject()) { |
554 Handle<JSObject> receiver = Handle<JSObject>::cast(object); | 553 Handle<JSObject> receiver = Handle<JSObject>::cast(object); |
555 if (receiver->map()->is_deprecated()) { | 554 if (receiver->map()->is_deprecated()) { |
556 use_ic = false; | |
557 JSObject::MigrateInstance(receiver); | 555 JSObject::MigrateInstance(receiver); |
558 } | 556 } |
559 } | 557 } |
560 | 558 |
561 // If the object is undefined or null it's illegal to try to get any | 559 // If the object is undefined or null it's illegal to try to get any |
562 // of its properties; throw a TypeError in that case. | 560 // of its properties; throw a TypeError in that case. |
563 if (object->IsUndefined() || object->IsNull()) { | 561 if (object->IsUndefined() || object->IsNull()) { |
564 return TypeError("non_object_property_call", object, name); | 562 return TypeError("non_object_property_call", object, name); |
565 } | 563 } |
566 | 564 |
(...skipping 18 matching lines...) Expand all Loading... |
585 | 583 |
586 if (!lookup.IsFound()) { | 584 if (!lookup.IsFound()) { |
587 // If the object does not have the requested property, check which | 585 // If the object does not have the requested property, check which |
588 // exception we need to throw. | 586 // exception we need to throw. |
589 return IsUndeclaredGlobal(object) | 587 return IsUndeclaredGlobal(object) |
590 ? ReferenceError("not_defined", name) | 588 ? ReferenceError("not_defined", name) |
591 : TypeError("undefined_method", object, name); | 589 : TypeError("undefined_method", object, name); |
592 } | 590 } |
593 | 591 |
594 // Lookup is valid: Update inline cache and stub cache. | 592 // Lookup is valid: Update inline cache and stub cache. |
595 if (use_ic) UpdateCaches(&lookup, state, extra_ic_state, object, name); | 593 if (FLAG_use_ic) { |
| 594 UpdateCaches(&lookup, state, extra_ic_state, object, name); |
| 595 } |
596 | 596 |
597 // Get the property. | 597 // Get the property. |
598 PropertyAttributes attr; | 598 PropertyAttributes attr; |
599 Handle<Object> result = | 599 Handle<Object> result = |
600 Object::GetProperty(object, object, &lookup, name, &attr); | 600 Object::GetProperty(object, object, &lookup, name, &attr); |
601 RETURN_IF_EMPTY_HANDLE(isolate(), result); | 601 RETURN_IF_EMPTY_HANDLE(isolate(), result); |
602 | 602 |
603 if (lookup.IsInterceptor() && attr == ABSENT) { | 603 if (lookup.IsInterceptor() && attr == ABSENT) { |
604 // If the object does not have the requested property, check which | 604 // If the object does not have the requested property, check which |
605 // exception we need to throw. | 605 // exception we need to throw. |
(...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
812 MaybeObject* KeyedCallIC::LoadFunction(State state, | 812 MaybeObject* KeyedCallIC::LoadFunction(State state, |
813 Handle<Object> object, | 813 Handle<Object> object, |
814 Handle<Object> key) { | 814 Handle<Object> key) { |
815 if (key->IsInternalizedString()) { | 815 if (key->IsInternalizedString()) { |
816 return CallICBase::LoadFunction(state, | 816 return CallICBase::LoadFunction(state, |
817 Code::kNoExtraICState, | 817 Code::kNoExtraICState, |
818 object, | 818 object, |
819 Handle<String>::cast(key)); | 819 Handle<String>::cast(key)); |
820 } | 820 } |
821 | 821 |
822 bool use_ic = FLAG_use_ic && !object->IsAccessCheckNeeded(); | |
823 if (object->IsJSObject()) { | 822 if (object->IsJSObject()) { |
824 Handle<JSObject> receiver = Handle<JSObject>::cast(object); | 823 Handle<JSObject> receiver = Handle<JSObject>::cast(object); |
825 if (receiver->map()->is_deprecated()) { | 824 if (receiver->map()->is_deprecated()) { |
826 use_ic = false; | |
827 JSObject::MigrateInstance(receiver); | 825 JSObject::MigrateInstance(receiver); |
828 } | 826 } |
829 } | 827 } |
830 | 828 |
831 if (object->IsUndefined() || object->IsNull()) { | 829 if (object->IsUndefined() || object->IsNull()) { |
832 return TypeError("non_object_property_call", object, key); | 830 return TypeError("non_object_property_call", object, key); |
833 } | 831 } |
834 | 832 |
| 833 bool use_ic = FLAG_use_ic && !object->IsAccessCheckNeeded(); |
835 ASSERT(!(use_ic && object->IsJSGlobalProxy())); | 834 ASSERT(!(use_ic && object->IsJSGlobalProxy())); |
836 | 835 |
837 if (use_ic && state != MEGAMORPHIC) { | 836 if (use_ic && state != MEGAMORPHIC) { |
838 int argc = target()->arguments_count(); | 837 int argc = target()->arguments_count(); |
839 Handle<Code> stub = isolate()->stub_cache()->ComputeCallMegamorphic( | 838 Handle<Code> stub = isolate()->stub_cache()->ComputeCallMegamorphic( |
840 argc, Code::KEYED_CALL_IC, Code::kNoExtraICState); | 839 argc, Code::KEYED_CALL_IC, Code::kNoExtraICState); |
841 if (object->IsJSObject()) { | 840 if (object->IsJSObject()) { |
842 Handle<JSObject> receiver = Handle<JSObject>::cast(object); | 841 Handle<JSObject> receiver = Handle<JSObject>::cast(object); |
843 if (receiver->elements()->map() == | 842 if (receiver->elements()->map() == |
844 isolate()->heap()->non_strict_arguments_elements_map()) { | 843 isolate()->heap()->non_strict_arguments_elements_map()) { |
(...skipping 23 matching lines...) Expand all Loading... |
868 | 867 |
869 MaybeObject* LoadIC::Load(State state, | 868 MaybeObject* LoadIC::Load(State state, |
870 Handle<Object> object, | 869 Handle<Object> object, |
871 Handle<String> name) { | 870 Handle<String> name) { |
872 // If the object is undefined or null it's illegal to try to get any | 871 // If the object is undefined or null it's illegal to try to get any |
873 // of its properties; throw a TypeError in that case. | 872 // of its properties; throw a TypeError in that case. |
874 if (object->IsUndefined() || object->IsNull()) { | 873 if (object->IsUndefined() || object->IsNull()) { |
875 return TypeError("non_object_property_load", object, name); | 874 return TypeError("non_object_property_load", object, name); |
876 } | 875 } |
877 | 876 |
878 bool use_ic = FLAG_use_ic; | 877 if (FLAG_use_ic) { |
879 | |
880 if (use_ic) { | |
881 // Use specialized code for getting the length of strings and | 878 // Use specialized code for getting the length of strings and |
882 // string wrapper objects. The length property of string wrapper | 879 // string wrapper objects. The length property of string wrapper |
883 // objects is read-only and therefore always returns the length of | 880 // objects is read-only and therefore always returns the length of |
884 // the underlying string value. See ECMA-262 15.5.5.1. | 881 // the underlying string value. See ECMA-262 15.5.5.1. |
885 if (object->IsStringWrapper() && | 882 if ((object->IsString() || object->IsStringWrapper()) && |
886 name->Equals(isolate()->heap()->length_string())) { | 883 name->Equals(isolate()->heap()->length_string())) { |
887 Handle<Code> stub; | 884 Handle<Code> stub; |
888 if (state == UNINITIALIZED) { | 885 if (state == UNINITIALIZED) { |
889 stub = pre_monomorphic_stub(); | 886 stub = pre_monomorphic_stub(); |
890 } else if (state == PREMONOMORPHIC || state == MONOMORPHIC) { | 887 } else if (state == PREMONOMORPHIC) { |
891 StringLengthStub string_length_stub(kind()); | 888 StringLengthStub string_length_stub(kind(), !object->IsString()); |
| 889 stub = string_length_stub.GetCode(isolate()); |
| 890 } else if (state == MONOMORPHIC && object->IsStringWrapper()) { |
| 891 StringLengthStub string_length_stub(kind(), true); |
892 stub = string_length_stub.GetCode(isolate()); | 892 stub = string_length_stub.GetCode(isolate()); |
893 } else if (state != MEGAMORPHIC) { | 893 } else if (state != MEGAMORPHIC) { |
894 ASSERT(state != GENERIC); | 894 ASSERT(state != GENERIC); |
895 stub = megamorphic_stub(); | 895 stub = megamorphic_stub(); |
896 } | 896 } |
897 if (!stub.is_null()) { | 897 if (!stub.is_null()) { |
898 set_target(*stub); | 898 set_target(*stub); |
899 #ifdef DEBUG | 899 #ifdef DEBUG |
900 if (FLAG_trace_ic) PrintF("[LoadIC : +#length /stringwrapper]\n"); | 900 if (FLAG_trace_ic) PrintF("[LoadIC : +#length /string]\n"); |
901 #endif | 901 #endif |
902 } | 902 } |
903 // Get the string if we have a string wrapper object. | 903 // Get the string if we have a string wrapper object. |
904 String* string = String::cast(JSValue::cast(*object)->value()); | 904 Handle<Object> string = object->IsJSValue() |
905 return Smi::FromInt(string->length()); | 905 ? Handle<Object>(Handle<JSValue>::cast(object)->value(), isolate()) |
| 906 : object; |
| 907 return Smi::FromInt(String::cast(*string)->length()); |
906 } | 908 } |
907 | 909 |
908 // Use specialized code for getting prototype of functions. | 910 // Use specialized code for getting prototype of functions. |
909 if (object->IsJSFunction() && | 911 if (object->IsJSFunction() && |
910 name->Equals(isolate()->heap()->prototype_string()) && | 912 name->Equals(isolate()->heap()->prototype_string()) && |
911 Handle<JSFunction>::cast(object)->should_have_prototype()) { | 913 Handle<JSFunction>::cast(object)->should_have_prototype()) { |
912 Handle<Code> stub; | 914 Handle<Code> stub; |
913 if (state == UNINITIALIZED) { | 915 if (state == UNINITIALIZED) { |
914 stub = pre_monomorphic_stub(); | 916 stub = pre_monomorphic_stub(); |
915 } else if (state == PREMONOMORPHIC) { | 917 } else if (state == PREMONOMORPHIC) { |
(...skipping 11 matching lines...) Expand all Loading... |
927 } | 929 } |
928 return *Accessors::FunctionGetPrototype(Handle<JSFunction>::cast(object)); | 930 return *Accessors::FunctionGetPrototype(Handle<JSFunction>::cast(object)); |
929 } | 931 } |
930 } | 932 } |
931 | 933 |
932 // Check if the name is trivially convertible to an index and get | 934 // Check if the name is trivially convertible to an index and get |
933 // the element or char if so. | 935 // the element or char if so. |
934 uint32_t index; | 936 uint32_t index; |
935 if (kind() == Code::KEYED_LOAD_IC && name->AsArrayIndex(&index)) { | 937 if (kind() == Code::KEYED_LOAD_IC && name->AsArrayIndex(&index)) { |
936 // Rewrite to the generic keyed load stub. | 938 // Rewrite to the generic keyed load stub. |
937 if (use_ic) set_target(*generic_stub()); | 939 if (FLAG_use_ic) set_target(*generic_stub()); |
938 return Runtime::GetElementOrCharAtOrFail(isolate(), object, index); | 940 return Runtime::GetElementOrCharAtOrFail(isolate(), object, index); |
939 } | 941 } |
940 | 942 |
941 if (object->IsJSObject()) { | 943 if (object->IsJSObject()) { |
942 Handle<JSObject> receiver = Handle<JSObject>::cast(object); | 944 Handle<JSObject> receiver = Handle<JSObject>::cast(object); |
943 if (receiver->map()->is_deprecated()) { | 945 if (receiver->map()->is_deprecated()) { |
944 use_ic = false; | |
945 JSObject::MigrateInstance(receiver); | 946 JSObject::MigrateInstance(receiver); |
946 } | 947 } |
947 } | 948 } |
948 | 949 |
949 // Named lookup in the object. | 950 // Named lookup in the object. |
950 LookupResult lookup(isolate()); | 951 LookupResult lookup(isolate()); |
951 LookupForRead(object, name, &lookup); | 952 LookupForRead(object, name, &lookup); |
952 | 953 |
953 // If we did not find a property, check if we need to throw an exception. | 954 // If we did not find a property, check if we need to throw an exception. |
954 if (!lookup.IsFound()) { | 955 if (!lookup.IsFound()) { |
955 if (IsUndeclaredGlobal(object)) { | 956 if (IsUndeclaredGlobal(object)) { |
956 return ReferenceError("not_defined", name); | 957 return ReferenceError("not_defined", name); |
957 } | 958 } |
958 LOG(isolate(), SuspectReadEvent(*name, *object)); | 959 LOG(isolate(), SuspectReadEvent(*name, *object)); |
959 } | 960 } |
960 | 961 |
961 // Update inline cache and stub cache. | 962 // Update inline cache and stub cache. |
962 if (use_ic) UpdateCaches(&lookup, state, object, name); | 963 if (FLAG_use_ic) UpdateCaches(&lookup, state, object, name); |
963 | 964 |
964 PropertyAttributes attr; | 965 PropertyAttributes attr; |
965 if (lookup.IsInterceptor() || lookup.IsHandler()) { | 966 if (lookup.IsInterceptor() || lookup.IsHandler()) { |
966 // Get the property. | 967 // Get the property. |
967 Handle<Object> result = | 968 Handle<Object> result = |
968 Object::GetProperty(object, object, &lookup, name, &attr); | 969 Object::GetProperty(object, object, &lookup, name, &attr); |
969 RETURN_IF_EMPTY_HANDLE(isolate(), result); | 970 RETURN_IF_EMPTY_HANDLE(isolate(), result); |
970 // If the property is not present, check if we need to throw an | 971 // If the property is not present, check if we need to throw an |
971 // exception. | 972 // exception. |
972 if (attr == ABSENT && IsUndeclaredGlobal(object)) { | 973 if (attr == ABSENT && IsUndeclaredGlobal(object)) { |
(...skipping 284 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1257 UNREACHABLE(); | 1258 UNREACHABLE(); |
1258 break; | 1259 break; |
1259 } | 1260 } |
1260 } | 1261 } |
1261 | 1262 |
1262 | 1263 |
1263 void LoadIC::UpdateCaches(LookupResult* lookup, | 1264 void LoadIC::UpdateCaches(LookupResult* lookup, |
1264 State state, | 1265 State state, |
1265 Handle<Object> object, | 1266 Handle<Object> object, |
1266 Handle<String> name) { | 1267 Handle<String> name) { |
1267 // TODO(verwaest): It would be nice to support loading fields from smis as | |
1268 // well. For now just fail to update the cache. | |
1269 if (!object->IsHeapObject()) return; | 1268 if (!object->IsHeapObject()) return; |
1270 | 1269 |
1271 Handle<HeapObject> receiver = Handle<HeapObject>::cast(object); | 1270 Handle<HeapObject> receiver = Handle<HeapObject>::cast(object); |
1272 | 1271 |
1273 Handle<Code> code; | 1272 Handle<Code> code; |
1274 if (state == UNINITIALIZED) { | 1273 if (state == UNINITIALIZED) { |
1275 // This is the first time we execute this inline cache. | 1274 // This is the first time we execute this inline cache. |
1276 // Set the target to the pre monomorphic stub to delay | 1275 // Set the target to the pre monomorphic stub to delay |
1277 // setting the monomorphic state. | 1276 // setting the monomorphic state. |
1278 code = pre_monomorphic_stub(); | 1277 code = pre_monomorphic_stub(); |
1279 } else if (!lookup->IsCacheable()) { | 1278 } else if (!lookup->IsCacheable()) { |
1280 // Bail out if the result is not cacheable. | 1279 // Bail out if the result is not cacheable. |
1281 code = slow_stub(); | 1280 code = slow_stub(); |
1282 } else if (object->IsString() && | |
1283 name->Equals(isolate()->heap()->length_string())) { | |
1284 int length_index = String::kLengthOffset / kPointerSize; | |
1285 if (target()->is_load_stub()) { | |
1286 LoadFieldStub stub(true, length_index, Representation::Tagged()); | |
1287 code = stub.GetCode(isolate()); | |
1288 } else { | |
1289 KeyedLoadFieldStub stub(true, length_index, Representation::Tagged()); | |
1290 code = stub.GetCode(isolate()); | |
1291 } | |
1292 } else if (!object->IsJSObject()) { | 1281 } else if (!object->IsJSObject()) { |
1293 // TODO(jkummerow): It would be nice to support non-JSObjects in | 1282 // TODO(jkummerow): It would be nice to support non-JSObjects in |
1294 // ComputeLoadHandler, then we wouldn't need to go generic here. | 1283 // ComputeLoadHandler, then we wouldn't need to go generic here. |
1295 code = slow_stub(); | 1284 code = slow_stub(); |
1296 } else { | 1285 } else { |
1297 code = ComputeLoadHandler(lookup, Handle<JSObject>::cast(receiver), name); | 1286 code = ComputeLoadHandler(lookup, Handle<JSObject>::cast(receiver), name); |
1298 if (code.is_null()) code = slow_stub(); | 1287 if (code.is_null()) code = slow_stub(); |
1299 } | 1288 } |
1300 | 1289 |
1301 PatchCache(state, kNonStrictMode, receiver, name, code); | 1290 PatchCache(state, kNonStrictMode, receiver, name, code); |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1366 CallOptimization call_optimization(function); | 1355 CallOptimization call_optimization(function); |
1367 if (call_optimization.is_simple_api_call() && | 1356 if (call_optimization.is_simple_api_call() && |
1368 call_optimization.IsCompatibleReceiver(*receiver) && | 1357 call_optimization.IsCompatibleReceiver(*receiver) && |
1369 FLAG_js_accessor_ics) { | 1358 FLAG_js_accessor_ics) { |
1370 return isolate()->stub_cache()->ComputeLoadCallback( | 1359 return isolate()->stub_cache()->ComputeLoadCallback( |
1371 name, receiver, holder, call_optimization); | 1360 name, receiver, holder, call_optimization); |
1372 } | 1361 } |
1373 return isolate()->stub_cache()->ComputeLoadViaGetter( | 1362 return isolate()->stub_cache()->ComputeLoadViaGetter( |
1374 name, receiver, holder, function); | 1363 name, receiver, holder, function); |
1375 } else if (receiver->IsJSArray() && | 1364 } else if (receiver->IsJSArray() && |
1376 name->Equals(isolate()->heap()->length_string())) { | 1365 name->Equals(isolate()->heap()->length_string())) { |
1377 PropertyIndex lengthIndex = PropertyIndex::NewHeaderIndex( | 1366 PropertyIndex lengthIndex = |
1378 JSArray::kLengthOffset / kPointerSize); | 1367 PropertyIndex::NewHeaderIndex(JSArray::kLengthOffset / kPointerSize); |
1379 return isolate()->stub_cache()->ComputeLoadField( | 1368 return isolate()->stub_cache()->ComputeLoadField( |
1380 name, receiver, holder, lengthIndex, Representation::Tagged()); | 1369 name, receiver, holder, lengthIndex, Representation::Tagged()); |
1381 } | 1370 } |
1382 // TODO(dcarney): Handle correctly. | 1371 // TODO(dcarney): Handle correctly. |
1383 if (callback->IsDeclaredAccessorInfo()) break; | 1372 if (callback->IsDeclaredAccessorInfo()) break; |
1384 ASSERT(callback->IsForeign()); | 1373 ASSERT(callback->IsForeign()); |
1385 // No IC support for old-style native accessors. | 1374 // No IC support for old-style native accessors. |
1386 break; | 1375 break; |
1387 } | 1376 } |
1388 case INTERCEPTOR: | 1377 case INTERCEPTOR: |
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1500 if (use_ic) { | 1489 if (use_ic) { |
1501 Handle<Code> stub = generic_stub(); | 1490 Handle<Code> stub = generic_stub(); |
1502 if (miss_mode != MISS_FORCE_GENERIC) { | 1491 if (miss_mode != MISS_FORCE_GENERIC) { |
1503 if (object->IsString() && key->IsNumber()) { | 1492 if (object->IsString() && key->IsNumber()) { |
1504 if (state == UNINITIALIZED) { | 1493 if (state == UNINITIALIZED) { |
1505 stub = string_stub(); | 1494 stub = string_stub(); |
1506 } | 1495 } |
1507 } else if (object->IsJSObject()) { | 1496 } else if (object->IsJSObject()) { |
1508 Handle<JSObject> receiver = Handle<JSObject>::cast(object); | 1497 Handle<JSObject> receiver = Handle<JSObject>::cast(object); |
1509 if (receiver->map()->is_deprecated()) { | 1498 if (receiver->map()->is_deprecated()) { |
1510 use_ic = false; | |
1511 JSObject::MigrateInstance(receiver); | 1499 JSObject::MigrateInstance(receiver); |
1512 } | 1500 } |
1513 | 1501 |
1514 if (receiver->elements()->map() == | 1502 if (receiver->elements()->map() == |
1515 isolate()->heap()->non_strict_arguments_elements_map()) { | 1503 isolate()->heap()->non_strict_arguments_elements_map()) { |
1516 stub = non_strict_arguments_stub(); | 1504 stub = non_strict_arguments_stub(); |
1517 } else if (receiver->HasIndexedInterceptor()) { | 1505 } else if (receiver->HasIndexedInterceptor()) { |
1518 stub = indexed_interceptor_stub(); | 1506 stub = indexed_interceptor_stub(); |
1519 } else if (!key->ToSmi()->IsFailure() && | 1507 } else if (!key->ToSmi()->IsFailure() && |
1520 (target() != *non_strict_arguments_stub())) { | 1508 (target() != *non_strict_arguments_stub())) { |
1521 stub = LoadElementStub(receiver); | 1509 stub = LoadElementStub(receiver); |
1522 } | 1510 } |
1523 } | 1511 } |
1524 } else { | 1512 } else { |
1525 TRACE_GENERIC_IC(isolate(), "KeyedLoadIC", "force generic"); | 1513 TRACE_GENERIC_IC(isolate(), "KeyedLoadIC", "force generic"); |
1526 } | 1514 } |
1527 if (use_ic) { | 1515 ASSERT(!stub.is_null()); |
1528 ASSERT(!stub.is_null()); | 1516 set_target(*stub); |
1529 set_target(*stub); | 1517 TRACE_IC("KeyedLoadIC", key, state, target()); |
1530 TRACE_IC("KeyedLoadIC", key, state, target()); | |
1531 } | |
1532 } | 1518 } |
1533 | 1519 |
1534 | 1520 |
1535 return Runtime::GetObjectPropertyOrFail(isolate(), object, key); | 1521 return Runtime::GetObjectPropertyOrFail(isolate(), object, key); |
1536 } | 1522 } |
1537 | 1523 |
1538 | 1524 |
1539 Handle<Code> KeyedLoadIC::ComputeLoadHandler(LookupResult* lookup, | 1525 Handle<Code> KeyedLoadIC::ComputeLoadHandler(LookupResult* lookup, |
1540 Handle<JSObject> receiver, | 1526 Handle<JSObject> receiver, |
1541 Handle<String> name) { | 1527 Handle<String> name) { |
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1685 name->Equals(isolate()->heap()->length_string())) { | 1671 name->Equals(isolate()->heap()->length_string())) { |
1686 return TypeError("strict_read_only_property", object, name); | 1672 return TypeError("strict_read_only_property", object, name); |
1687 } | 1673 } |
1688 | 1674 |
1689 // Ignore other stores where the receiver is not a JSObject. | 1675 // Ignore other stores where the receiver is not a JSObject. |
1690 // TODO(1475): Must check prototype chains of object wrappers. | 1676 // TODO(1475): Must check prototype chains of object wrappers. |
1691 if (!object->IsJSObject()) return *value; | 1677 if (!object->IsJSObject()) return *value; |
1692 | 1678 |
1693 Handle<JSObject> receiver = Handle<JSObject>::cast(object); | 1679 Handle<JSObject> receiver = Handle<JSObject>::cast(object); |
1694 | 1680 |
1695 bool use_ic = FLAG_use_ic; | |
1696 if (receiver->map()->is_deprecated()) { | 1681 if (receiver->map()->is_deprecated()) { |
1697 use_ic = false; | |
1698 JSObject::MigrateInstance(receiver); | 1682 JSObject::MigrateInstance(receiver); |
1699 } | 1683 } |
1700 | 1684 |
1701 // Check if the given name is an array index. | 1685 // Check if the given name is an array index. |
1702 uint32_t index; | 1686 uint32_t index; |
1703 if (name->AsArrayIndex(&index)) { | 1687 if (name->AsArrayIndex(&index)) { |
1704 Handle<Object> result = | 1688 Handle<Object> result = |
1705 JSObject::SetElement(receiver, index, value, NONE, strict_mode); | 1689 JSObject::SetElement(receiver, index, value, NONE, strict_mode); |
1706 RETURN_IF_EMPTY_HANDLE(isolate(), result); | 1690 RETURN_IF_EMPTY_HANDLE(isolate(), result); |
1707 return *value; | 1691 return *value; |
1708 } | 1692 } |
1709 | 1693 |
1710 // Observed objects are always modified through the runtime. | 1694 // Observed objects are always modified through the runtime. |
1711 if (FLAG_harmony_observation && receiver->map()->is_observed()) { | 1695 if (FLAG_harmony_observation && receiver->map()->is_observed()) { |
1712 return JSReceiver::SetPropertyOrFail( | 1696 return JSReceiver::SetPropertyOrFail( |
1713 receiver, name, value, NONE, strict_mode, store_mode); | 1697 receiver, name, value, NONE, strict_mode, store_mode); |
1714 } | 1698 } |
1715 | 1699 |
1716 // Use specialized code for setting the length of arrays with fast | 1700 // Use specialized code for setting the length of arrays with fast |
1717 // properties. Slow properties might indicate redefinition of the length | 1701 // properties. Slow properties might indicate redefinition of the length |
1718 // property. Note that when redefined using Object.freeze, it's possible | 1702 // property. Note that when redefined using Object.freeze, it's possible |
1719 // to have fast properties but a read-only length. | 1703 // to have fast properties but a read-only length. |
1720 if (use_ic && | 1704 if (FLAG_use_ic && |
1721 receiver->IsJSArray() && | 1705 receiver->IsJSArray() && |
1722 name->Equals(isolate()->heap()->length_string()) && | 1706 name->Equals(isolate()->heap()->length_string()) && |
1723 Handle<JSArray>::cast(receiver)->AllowsSetElementsLength() && | 1707 Handle<JSArray>::cast(receiver)->AllowsSetElementsLength() && |
1724 receiver->HasFastProperties() && | 1708 receiver->HasFastProperties() && |
1725 !receiver->map()->is_frozen()) { | 1709 !receiver->map()->is_frozen()) { |
1726 Handle<Code> stub = | 1710 Handle<Code> stub = |
1727 StoreArrayLengthStub(kind(), strict_mode).GetCode(isolate()); | 1711 StoreArrayLengthStub(kind(), strict_mode).GetCode(isolate()); |
1728 set_target(*stub); | 1712 set_target(*stub); |
1729 TRACE_IC("StoreIC", name, state, *stub); | 1713 TRACE_IC("StoreIC", name, state, *stub); |
1730 return JSReceiver::SetPropertyOrFail( | 1714 return JSReceiver::SetPropertyOrFail( |
1731 receiver, name, value, NONE, strict_mode, store_mode); | 1715 receiver, name, value, NONE, strict_mode, store_mode); |
1732 } | 1716 } |
1733 | 1717 |
1734 if (receiver->IsJSGlobalProxy()) { | 1718 if (receiver->IsJSGlobalProxy()) { |
1735 if (use_ic && kind() != Code::KEYED_STORE_IC) { | 1719 if (FLAG_use_ic && kind() != Code::KEYED_STORE_IC) { |
1736 // Generate a generic stub that goes to the runtime when we see a global | 1720 // Generate a generic stub that goes to the runtime when we see a global |
1737 // proxy as receiver. | 1721 // proxy as receiver. |
1738 Handle<Code> stub = (strict_mode == kStrictMode) | 1722 Handle<Code> stub = (strict_mode == kStrictMode) |
1739 ? global_proxy_stub_strict() | 1723 ? global_proxy_stub_strict() |
1740 : global_proxy_stub(); | 1724 : global_proxy_stub(); |
1741 set_target(*stub); | 1725 set_target(*stub); |
1742 TRACE_IC("StoreIC", name, state, *stub); | 1726 TRACE_IC("StoreIC", name, state, *stub); |
1743 } | 1727 } |
1744 return JSReceiver::SetPropertyOrFail( | 1728 return JSReceiver::SetPropertyOrFail( |
1745 receiver, name, value, NONE, strict_mode, store_mode); | 1729 receiver, name, value, NONE, strict_mode, store_mode); |
1746 } | 1730 } |
1747 | 1731 |
1748 LookupResult lookup(isolate()); | 1732 LookupResult lookup(isolate()); |
1749 bool can_store = LookupForWrite(receiver, name, value, &lookup, &state); | 1733 bool can_store = LookupForWrite(receiver, name, value, &lookup, &state); |
1750 if (!can_store && | 1734 if (!can_store && |
1751 strict_mode == kStrictMode && | 1735 strict_mode == kStrictMode && |
1752 !(lookup.IsProperty() && lookup.IsReadOnly()) && | 1736 !(lookup.IsProperty() && lookup.IsReadOnly()) && |
1753 IsUndeclaredGlobal(object)) { | 1737 IsUndeclaredGlobal(object)) { |
1754 // Strict mode doesn't allow setting non-existent global property. | 1738 // Strict mode doesn't allow setting non-existent global property. |
1755 return ReferenceError("not_defined", name); | 1739 return ReferenceError("not_defined", name); |
1756 } | 1740 } |
1757 if (use_ic) { | 1741 if (FLAG_use_ic) { |
1758 if (state == UNINITIALIZED) { | 1742 if (state == UNINITIALIZED) { |
1759 Handle<Code> stub = (strict_mode == kStrictMode) | 1743 Handle<Code> stub = (strict_mode == kStrictMode) |
1760 ? pre_monomorphic_stub_strict() | 1744 ? pre_monomorphic_stub_strict() |
1761 : pre_monomorphic_stub(); | 1745 : pre_monomorphic_stub(); |
1762 set_target(*stub); | 1746 set_target(*stub); |
1763 TRACE_IC("StoreIC", name, state, *stub); | 1747 TRACE_IC("StoreIC", name, state, *stub); |
1764 } else if (can_store) { | 1748 } else if (can_store) { |
1765 UpdateCaches(&lookup, state, strict_mode, receiver, name, value); | 1749 UpdateCaches(&lookup, state, strict_mode, receiver, name, value); |
1766 } else if (!name->IsCacheable(isolate()) || | 1750 } else if (!name->IsCacheable(isolate()) || |
1767 lookup.IsNormal() || | 1751 lookup.IsNormal() || |
(...skipping 1381 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3149 #undef ADDR | 3133 #undef ADDR |
3150 }; | 3134 }; |
3151 | 3135 |
3152 | 3136 |
3153 Address IC::AddressFromUtilityId(IC::UtilityId id) { | 3137 Address IC::AddressFromUtilityId(IC::UtilityId id) { |
3154 return IC_utilities[id]; | 3138 return IC_utilities[id]; |
3155 } | 3139 } |
3156 | 3140 |
3157 | 3141 |
3158 } } // namespace v8::internal | 3142 } } // namespace v8::internal |
OLD | NEW |