| 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 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1358 name, receiver, holder, info); | 1347 name, receiver, holder, info); |
| 1359 } else if (callback->IsAccessorPair()) { | 1348 } else if (callback->IsAccessorPair()) { |
| 1360 Handle<Object> getter(Handle<AccessorPair>::cast(callback)->getter(), | 1349 Handle<Object> getter(Handle<AccessorPair>::cast(callback)->getter(), |
| 1361 isolate()); | 1350 isolate()); |
| 1362 if (!getter->IsJSFunction()) break; | 1351 if (!getter->IsJSFunction()) break; |
| 1363 if (holder->IsGlobalObject()) break; | 1352 if (holder->IsGlobalObject()) break; |
| 1364 if (!holder->HasFastProperties()) break; | 1353 if (!holder->HasFastProperties()) break; |
| 1365 Handle<JSFunction> function = Handle<JSFunction>::cast(getter); | 1354 Handle<JSFunction> function = Handle<JSFunction>::cast(getter); |
| 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) && |
| 1358 FLAG_js_accessor_ics) { |
| 1369 return isolate()->stub_cache()->ComputeLoadCallback( | 1359 return isolate()->stub_cache()->ComputeLoadCallback( |
| 1370 name, receiver, holder, call_optimization); | 1360 name, receiver, holder, call_optimization); |
| 1371 } | 1361 } |
| 1372 return isolate()->stub_cache()->ComputeLoadViaGetter( | 1362 return isolate()->stub_cache()->ComputeLoadViaGetter( |
| 1373 name, receiver, holder, function); | 1363 name, receiver, holder, function); |
| 1374 } else if (receiver->IsJSArray() && | 1364 } else if (receiver->IsJSArray() && |
| 1375 name->Equals(isolate()->heap()->length_string())) { | 1365 name->Equals(isolate()->heap()->length_string())) { |
| 1376 PropertyIndex lengthIndex = PropertyIndex::NewHeaderIndex( | 1366 PropertyIndex lengthIndex = |
| 1377 JSArray::kLengthOffset / kPointerSize); | 1367 PropertyIndex::NewHeaderIndex(JSArray::kLengthOffset / kPointerSize); |
| 1378 return isolate()->stub_cache()->ComputeLoadField( | 1368 return isolate()->stub_cache()->ComputeLoadField( |
| 1379 name, receiver, holder, lengthIndex, Representation::Tagged()); | 1369 name, receiver, holder, lengthIndex, Representation::Tagged()); |
| 1380 } | 1370 } |
| 1381 // TODO(dcarney): Handle correctly. | 1371 // TODO(dcarney): Handle correctly. |
| 1382 if (callback->IsDeclaredAccessorInfo()) break; | 1372 if (callback->IsDeclaredAccessorInfo()) break; |
| 1383 ASSERT(callback->IsForeign()); | 1373 ASSERT(callback->IsForeign()); |
| 1384 // No IC support for old-style native accessors. | 1374 // No IC support for old-style native accessors. |
| 1385 break; | 1375 break; |
| 1386 } | 1376 } |
| 1387 case INTERCEPTOR: | 1377 case INTERCEPTOR: |
| (...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1499 if (use_ic) { | 1489 if (use_ic) { |
| 1500 Handle<Code> stub = generic_stub(); | 1490 Handle<Code> stub = generic_stub(); |
| 1501 if (miss_mode != MISS_FORCE_GENERIC) { | 1491 if (miss_mode != MISS_FORCE_GENERIC) { |
| 1502 if (object->IsString() && key->IsNumber()) { | 1492 if (object->IsString() && key->IsNumber()) { |
| 1503 if (state == UNINITIALIZED) { | 1493 if (state == UNINITIALIZED) { |
| 1504 stub = string_stub(); | 1494 stub = string_stub(); |
| 1505 } | 1495 } |
| 1506 } else if (object->IsJSObject()) { | 1496 } else if (object->IsJSObject()) { |
| 1507 Handle<JSObject> receiver = Handle<JSObject>::cast(object); | 1497 Handle<JSObject> receiver = Handle<JSObject>::cast(object); |
| 1508 if (receiver->map()->is_deprecated()) { | 1498 if (receiver->map()->is_deprecated()) { |
| 1509 use_ic = false; | |
| 1510 JSObject::MigrateInstance(receiver); | 1499 JSObject::MigrateInstance(receiver); |
| 1511 } | 1500 } |
| 1512 | 1501 |
| 1513 if (receiver->elements()->map() == | 1502 if (receiver->elements()->map() == |
| 1514 isolate()->heap()->non_strict_arguments_elements_map()) { | 1503 isolate()->heap()->non_strict_arguments_elements_map()) { |
| 1515 stub = non_strict_arguments_stub(); | 1504 stub = non_strict_arguments_stub(); |
| 1516 } else if (receiver->HasIndexedInterceptor()) { | 1505 } else if (receiver->HasIndexedInterceptor()) { |
| 1517 stub = indexed_interceptor_stub(); | 1506 stub = indexed_interceptor_stub(); |
| 1518 } else if (!key->ToSmi()->IsFailure() && | 1507 } else if (!key->ToSmi()->IsFailure() && |
| 1519 (target() != *non_strict_arguments_stub())) { | 1508 (target() != *non_strict_arguments_stub())) { |
| 1520 stub = LoadElementStub(receiver); | 1509 stub = LoadElementStub(receiver); |
| 1521 } | 1510 } |
| 1522 } | 1511 } |
| 1523 } else { | 1512 } else { |
| 1524 TRACE_GENERIC_IC(isolate(), "KeyedLoadIC", "force generic"); | 1513 TRACE_GENERIC_IC(isolate(), "KeyedLoadIC", "force generic"); |
| 1525 } | 1514 } |
| 1526 if (use_ic) { | 1515 ASSERT(!stub.is_null()); |
| 1527 ASSERT(!stub.is_null()); | 1516 set_target(*stub); |
| 1528 set_target(*stub); | 1517 TRACE_IC("KeyedLoadIC", key, state, target()); |
| 1529 TRACE_IC("KeyedLoadIC", key, state, target()); | |
| 1530 } | |
| 1531 } | 1518 } |
| 1532 | 1519 |
| 1533 | 1520 |
| 1534 return Runtime::GetObjectPropertyOrFail(isolate(), object, key); | 1521 return Runtime::GetObjectPropertyOrFail(isolate(), object, key); |
| 1535 } | 1522 } |
| 1536 | 1523 |
| 1537 | 1524 |
| 1538 Handle<Code> KeyedLoadIC::ComputeLoadHandler(LookupResult* lookup, | 1525 Handle<Code> KeyedLoadIC::ComputeLoadHandler(LookupResult* lookup, |
| 1539 Handle<JSObject> receiver, | 1526 Handle<JSObject> receiver, |
| 1540 Handle<String> name) { | 1527 Handle<String> name) { |
| (...skipping 28 matching lines...) Expand all Loading... |
| 1569 } else if (callback_object->IsAccessorPair()) { | 1556 } else if (callback_object->IsAccessorPair()) { |
| 1570 Handle<Object> getter( | 1557 Handle<Object> getter( |
| 1571 Handle<AccessorPair>::cast(callback_object)->getter(), | 1558 Handle<AccessorPair>::cast(callback_object)->getter(), |
| 1572 isolate()); | 1559 isolate()); |
| 1573 if (!getter->IsJSFunction()) break; | 1560 if (!getter->IsJSFunction()) break; |
| 1574 if (holder->IsGlobalObject()) break; | 1561 if (holder->IsGlobalObject()) break; |
| 1575 if (!holder->HasFastProperties()) break; | 1562 if (!holder->HasFastProperties()) break; |
| 1576 Handle<JSFunction> function = Handle<JSFunction>::cast(getter); | 1563 Handle<JSFunction> function = Handle<JSFunction>::cast(getter); |
| 1577 CallOptimization call_optimization(function); | 1564 CallOptimization call_optimization(function); |
| 1578 if (call_optimization.is_simple_api_call() && | 1565 if (call_optimization.is_simple_api_call() && |
| 1579 call_optimization.IsCompatibleReceiver(*receiver)) { | 1566 call_optimization.IsCompatibleReceiver(*receiver) && |
| 1567 FLAG_js_accessor_ics) { |
| 1580 return isolate()->stub_cache()->ComputeKeyedLoadCallback( | 1568 return isolate()->stub_cache()->ComputeKeyedLoadCallback( |
| 1581 name, receiver, holder, call_optimization); | 1569 name, receiver, holder, call_optimization); |
| 1582 } | 1570 } |
| 1583 } | 1571 } |
| 1584 break; | 1572 break; |
| 1585 } | 1573 } |
| 1586 case INTERCEPTOR: | 1574 case INTERCEPTOR: |
| 1587 ASSERT(HasInterceptorGetter(lookup->holder())); | 1575 ASSERT(HasInterceptorGetter(lookup->holder())); |
| 1588 return isolate()->stub_cache()->ComputeKeyedLoadInterceptor( | 1576 return isolate()->stub_cache()->ComputeKeyedLoadInterceptor( |
| 1589 name, receiver, holder); | 1577 name, receiver, holder); |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1661 | 1649 |
| 1662 | 1650 |
| 1663 MaybeObject* StoreIC::Store(State state, | 1651 MaybeObject* StoreIC::Store(State state, |
| 1664 StrictModeFlag strict_mode, | 1652 StrictModeFlag strict_mode, |
| 1665 Handle<Object> object, | 1653 Handle<Object> object, |
| 1666 Handle<String> name, | 1654 Handle<String> name, |
| 1667 Handle<Object> value, | 1655 Handle<Object> value, |
| 1668 JSReceiver::StoreFromKeyed store_mode) { | 1656 JSReceiver::StoreFromKeyed store_mode) { |
| 1669 // Handle proxies. | 1657 // Handle proxies. |
| 1670 if (object->IsJSProxy()) { | 1658 if (object->IsJSProxy()) { |
| 1671 Handle<Object> result = JSReceiver::SetProperty( | 1659 return JSReceiver::SetPropertyOrFail( |
| 1672 Handle<JSReceiver>::cast(object), name, value, NONE, strict_mode); | 1660 Handle<JSReceiver>::cast(object), name, value, NONE, strict_mode); |
| 1673 RETURN_IF_EMPTY_HANDLE(isolate(), result); | |
| 1674 return *result; | |
| 1675 } | 1661 } |
| 1676 | 1662 |
| 1677 // If the object is undefined or null it's illegal to try to set any | 1663 // If the object is undefined or null it's illegal to try to set any |
| 1678 // properties on it; throw a TypeError in that case. | 1664 // properties on it; throw a TypeError in that case. |
| 1679 if (object->IsUndefined() || object->IsNull()) { | 1665 if (object->IsUndefined() || object->IsNull()) { |
| 1680 return TypeError("non_object_property_store", object, name); | 1666 return TypeError("non_object_property_store", object, name); |
| 1681 } | 1667 } |
| 1682 | 1668 |
| 1683 // The length property of string values is read-only. Throw in strict mode. | 1669 // The length property of string values is read-only. Throw in strict mode. |
| 1684 if (strict_mode == kStrictMode && object->IsString() && | 1670 if (strict_mode == kStrictMode && object->IsString() && |
| 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 Handle<Object> result = JSReceiver::SetProperty( | 1696 return JSReceiver::SetPropertyOrFail( |
| 1713 receiver, name, value, NONE, strict_mode, store_mode); | 1697 receiver, name, value, NONE, strict_mode, store_mode); |
| 1714 RETURN_IF_EMPTY_HANDLE(isolate(), result); | |
| 1715 return *result; | |
| 1716 } | 1698 } |
| 1717 | 1699 |
| 1718 // Use specialized code for setting the length of arrays with fast | 1700 // Use specialized code for setting the length of arrays with fast |
| 1719 // properties. Slow properties might indicate redefinition of the length | 1701 // properties. Slow properties might indicate redefinition of the length |
| 1720 // property. Note that when redefined using Object.freeze, it's possible | 1702 // property. Note that when redefined using Object.freeze, it's possible |
| 1721 // to have fast properties but a read-only length. | 1703 // to have fast properties but a read-only length. |
| 1722 if (use_ic && | 1704 if (FLAG_use_ic && |
| 1723 receiver->IsJSArray() && | 1705 receiver->IsJSArray() && |
| 1724 name->Equals(isolate()->heap()->length_string()) && | 1706 name->Equals(isolate()->heap()->length_string()) && |
| 1725 Handle<JSArray>::cast(receiver)->AllowsSetElementsLength() && | 1707 Handle<JSArray>::cast(receiver)->AllowsSetElementsLength() && |
| 1726 receiver->HasFastProperties() && | 1708 receiver->HasFastProperties() && |
| 1727 !receiver->map()->is_frozen()) { | 1709 !receiver->map()->is_frozen()) { |
| 1728 Handle<Code> stub = | 1710 Handle<Code> stub = |
| 1729 StoreArrayLengthStub(kind(), strict_mode).GetCode(isolate()); | 1711 StoreArrayLengthStub(kind(), strict_mode).GetCode(isolate()); |
| 1730 set_target(*stub); | 1712 set_target(*stub); |
| 1731 TRACE_IC("StoreIC", name, state, *stub); | 1713 TRACE_IC("StoreIC", name, state, *stub); |
| 1732 Handle<Object> result = JSReceiver::SetProperty( | 1714 return JSReceiver::SetPropertyOrFail( |
| 1733 receiver, name, value, NONE, strict_mode, store_mode); | 1715 receiver, name, value, NONE, strict_mode, store_mode); |
| 1734 RETURN_IF_EMPTY_HANDLE(isolate(), result); | |
| 1735 return *result; | |
| 1736 } | 1716 } |
| 1737 | 1717 |
| 1738 if (receiver->IsJSGlobalProxy()) { | 1718 if (receiver->IsJSGlobalProxy()) { |
| 1739 if (use_ic && kind() != Code::KEYED_STORE_IC) { | 1719 if (FLAG_use_ic && kind() != Code::KEYED_STORE_IC) { |
| 1740 // 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 |
| 1741 // proxy as receiver. | 1721 // proxy as receiver. |
| 1742 Handle<Code> stub = (strict_mode == kStrictMode) | 1722 Handle<Code> stub = (strict_mode == kStrictMode) |
| 1743 ? global_proxy_stub_strict() | 1723 ? global_proxy_stub_strict() |
| 1744 : global_proxy_stub(); | 1724 : global_proxy_stub(); |
| 1745 set_target(*stub); | 1725 set_target(*stub); |
| 1746 TRACE_IC("StoreIC", name, state, *stub); | 1726 TRACE_IC("StoreIC", name, state, *stub); |
| 1747 } | 1727 } |
| 1748 Handle<Object> result = JSReceiver::SetProperty( | 1728 return JSReceiver::SetPropertyOrFail( |
| 1749 receiver, name, value, NONE, strict_mode, store_mode); | 1729 receiver, name, value, NONE, strict_mode, store_mode); |
| 1750 RETURN_IF_EMPTY_HANDLE(isolate(), result); | |
| 1751 return *result; | |
| 1752 } | 1730 } |
| 1753 | 1731 |
| 1754 LookupResult lookup(isolate()); | 1732 LookupResult lookup(isolate()); |
| 1755 bool can_store = LookupForWrite(receiver, name, value, &lookup, &state); | 1733 bool can_store = LookupForWrite(receiver, name, value, &lookup, &state); |
| 1756 if (!can_store && | 1734 if (!can_store && |
| 1757 strict_mode == kStrictMode && | 1735 strict_mode == kStrictMode && |
| 1758 !(lookup.IsProperty() && lookup.IsReadOnly()) && | 1736 !(lookup.IsProperty() && lookup.IsReadOnly()) && |
| 1759 IsUndeclaredGlobal(object)) { | 1737 IsUndeclaredGlobal(object)) { |
| 1760 // Strict mode doesn't allow setting non-existent global property. | 1738 // Strict mode doesn't allow setting non-existent global property. |
| 1761 return ReferenceError("not_defined", name); | 1739 return ReferenceError("not_defined", name); |
| 1762 } | 1740 } |
| 1763 if (use_ic) { | 1741 if (FLAG_use_ic) { |
| 1764 if (state == UNINITIALIZED) { | 1742 if (state == UNINITIALIZED) { |
| 1765 Handle<Code> stub = (strict_mode == kStrictMode) | 1743 Handle<Code> stub = (strict_mode == kStrictMode) |
| 1766 ? pre_monomorphic_stub_strict() | 1744 ? pre_monomorphic_stub_strict() |
| 1767 : pre_monomorphic_stub(); | 1745 : pre_monomorphic_stub(); |
| 1768 set_target(*stub); | 1746 set_target(*stub); |
| 1769 TRACE_IC("StoreIC", name, state, *stub); | 1747 TRACE_IC("StoreIC", name, state, *stub); |
| 1770 } else if (can_store) { | 1748 } else if (can_store) { |
| 1771 UpdateCaches(&lookup, state, strict_mode, receiver, name, value); | 1749 UpdateCaches(&lookup, state, strict_mode, receiver, name, value); |
| 1772 } else if (!name->IsCacheable(isolate()) || | 1750 } else if (!name->IsCacheable(isolate()) || |
| 1773 lookup.IsNormal() || | 1751 lookup.IsNormal() || |
| 1774 (lookup.IsField() && lookup.CanHoldValue(value))) { | 1752 (lookup.IsField() && lookup.CanHoldValue(value))) { |
| 1775 Handle<Code> stub = (strict_mode == kStrictMode) ? generic_stub_strict() | 1753 Handle<Code> stub = (strict_mode == kStrictMode) ? generic_stub_strict() |
| 1776 : generic_stub(); | 1754 : generic_stub(); |
| 1777 set_target(*stub); | 1755 set_target(*stub); |
| 1778 } | 1756 } |
| 1779 } | 1757 } |
| 1780 | 1758 |
| 1781 // Set the property. | 1759 // Set the property. |
| 1782 Handle<Object> result = JSReceiver::SetProperty( | 1760 return JSReceiver::SetPropertyOrFail( |
| 1783 receiver, name, value, NONE, strict_mode, store_mode); | 1761 receiver, name, value, NONE, strict_mode, store_mode); |
| 1784 RETURN_IF_EMPTY_HANDLE(isolate(), result); | |
| 1785 return *result; | |
| 1786 } | 1762 } |
| 1787 | 1763 |
| 1788 | 1764 |
| 1789 void StoreIC::UpdateCaches(LookupResult* lookup, | 1765 void StoreIC::UpdateCaches(LookupResult* lookup, |
| 1790 State state, | 1766 State state, |
| 1791 StrictModeFlag strict_mode, | 1767 StrictModeFlag strict_mode, |
| 1792 Handle<JSObject> receiver, | 1768 Handle<JSObject> receiver, |
| 1793 Handle<String> name, | 1769 Handle<String> name, |
| 1794 Handle<Object> value) { | 1770 Handle<Object> value) { |
| 1795 ASSERT(!receiver->IsJSGlobalProxy()); | 1771 ASSERT(!receiver->IsJSGlobalProxy()); |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1847 name, receiver, holder, info, strict_mode); | 1823 name, receiver, holder, info, strict_mode); |
| 1848 } else if (callback->IsAccessorPair()) { | 1824 } else if (callback->IsAccessorPair()) { |
| 1849 Handle<Object> setter( | 1825 Handle<Object> setter( |
| 1850 Handle<AccessorPair>::cast(callback)->setter(), isolate()); | 1826 Handle<AccessorPair>::cast(callback)->setter(), isolate()); |
| 1851 if (!setter->IsJSFunction()) break; | 1827 if (!setter->IsJSFunction()) break; |
| 1852 if (holder->IsGlobalObject()) break; | 1828 if (holder->IsGlobalObject()) break; |
| 1853 if (!holder->HasFastProperties()) break; | 1829 if (!holder->HasFastProperties()) break; |
| 1854 Handle<JSFunction> function = Handle<JSFunction>::cast(setter); | 1830 Handle<JSFunction> function = Handle<JSFunction>::cast(setter); |
| 1855 CallOptimization call_optimization(function); | 1831 CallOptimization call_optimization(function); |
| 1856 if (call_optimization.is_simple_api_call() && | 1832 if (call_optimization.is_simple_api_call() && |
| 1857 call_optimization.IsCompatibleReceiver(*receiver)) { | 1833 call_optimization.IsCompatibleReceiver(*receiver) && |
| 1834 FLAG_js_accessor_ics) { |
| 1858 return isolate()->stub_cache()->ComputeStoreCallback( | 1835 return isolate()->stub_cache()->ComputeStoreCallback( |
| 1859 name, receiver, holder, call_optimization, strict_mode); | 1836 name, receiver, holder, call_optimization, strict_mode); |
| 1860 } | 1837 } |
| 1861 return isolate()->stub_cache()->ComputeStoreViaSetter( | 1838 return isolate()->stub_cache()->ComputeStoreViaSetter( |
| 1862 name, receiver, holder, Handle<JSFunction>::cast(setter), | 1839 name, receiver, holder, Handle<JSFunction>::cast(setter), |
| 1863 strict_mode); | 1840 strict_mode); |
| 1864 } | 1841 } |
| 1865 // TODO(dcarney): Handle correctly. | 1842 // TODO(dcarney): Handle correctly. |
| 1866 if (callback->IsDeclaredAccessorInfo()) break; | 1843 if (callback->IsDeclaredAccessorInfo()) break; |
| 1867 ASSERT(callback->IsForeign()); | 1844 ASSERT(callback->IsForeign()); |
| (...skipping 1288 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3156 #undef ADDR | 3133 #undef ADDR |
| 3157 }; | 3134 }; |
| 3158 | 3135 |
| 3159 | 3136 |
| 3160 Address IC::AddressFromUtilityId(IC::UtilityId id) { | 3137 Address IC::AddressFromUtilityId(IC::UtilityId id) { |
| 3161 return IC_utilities[id]; | 3138 return IC_utilities[id]; |
| 3162 } | 3139 } |
| 3163 | 3140 |
| 3164 | 3141 |
| 3165 } } // namespace v8::internal | 3142 } } // namespace v8::internal |
| OLD | NEW |