Chromium Code Reviews| 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 521 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 532 // Change the receiver to the result of calling ToObject on it. | 532 // Change the receiver to the result of calling ToObject on it. |
| 533 const int argc = this->target()->arguments_count(); | 533 const int argc = this->target()->arguments_count(); |
| 534 StackFrameLocator locator(isolate()); | 534 StackFrameLocator locator(isolate()); |
| 535 JavaScriptFrame* frame = locator.FindJavaScriptFrame(0); | 535 JavaScriptFrame* frame = locator.FindJavaScriptFrame(0); |
| 536 int index = frame->ComputeExpressionsCount() - (argc + 1); | 536 int index = frame->ComputeExpressionsCount() - (argc + 1); |
| 537 frame->SetExpression(index, *isolate()->factory()->ToObject(object)); | 537 frame->SetExpression(index, *isolate()->factory()->ToObject(object)); |
| 538 } | 538 } |
| 539 } | 539 } |
| 540 | 540 |
| 541 | 541 |
| 542 static bool MigrateDeprecated(Handle<Object> object) { | |
| 543 if (!object->IsJSObject()) return false; | |
| 544 Handle<JSObject> receiver = Handle<JSObject>::cast(object); | |
| 545 if (!receiver->map()->is_deprecated()) return false; | |
| 546 JSObject::MigrateInstance(Handle<JSObject>::cast(object)); | |
| 547 return true; | |
| 548 } | |
| 549 | |
| 550 | |
| 542 MaybeObject* CallICBase::LoadFunction(Handle<Object> object, | 551 MaybeObject* CallICBase::LoadFunction(Handle<Object> object, |
| 543 Handle<String> name) { | 552 Handle<String> name) { |
| 544 bool use_ic = FLAG_use_ic; | 553 bool use_ic = MigrateDeprecated(object) ? false : FLAG_use_ic; |
| 545 if (object->IsJSObject()) { | |
| 546 Handle<JSObject> receiver = Handle<JSObject>::cast(object); | |
| 547 if (receiver->map()->is_deprecated()) { | |
| 548 use_ic = false; | |
| 549 JSObject::MigrateInstance(receiver); | |
| 550 } | |
| 551 } | |
| 552 | 554 |
| 553 // If the object is undefined or null it's illegal to try to get any | 555 // If the object is undefined or null it's illegal to try to get any |
| 554 // of its properties; throw a TypeError in that case. | 556 // of its properties; throw a TypeError in that case. |
| 555 if (object->IsUndefined() || object->IsNull()) { | 557 if (object->IsUndefined() || object->IsNull()) { |
| 556 return TypeError("non_object_property_call", object, name); | 558 return TypeError("non_object_property_call", object, name); |
| 557 } | 559 } |
| 558 | 560 |
| 559 // Check if the name is trivially convertible to an index and get | 561 // Check if the name is trivially convertible to an index and get |
| 560 // the element if so. | 562 // the element if so. |
| 561 uint32_t index; | 563 uint32_t index; |
| (...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 789 TRACE_IC(kind_ == Code::CALL_IC ? "CallIC" : "KeyedCallIC", name, target()); | 791 TRACE_IC(kind_ == Code::CALL_IC ? "CallIC" : "KeyedCallIC", name, target()); |
| 790 } | 792 } |
| 791 | 793 |
| 792 | 794 |
| 793 MaybeObject* KeyedCallIC::LoadFunction(Handle<Object> object, | 795 MaybeObject* KeyedCallIC::LoadFunction(Handle<Object> object, |
| 794 Handle<Object> key) { | 796 Handle<Object> key) { |
| 795 if (key->IsInternalizedString()) { | 797 if (key->IsInternalizedString()) { |
| 796 return CallICBase::LoadFunction(object, Handle<String>::cast(key)); | 798 return CallICBase::LoadFunction(object, Handle<String>::cast(key)); |
| 797 } | 799 } |
| 798 | 800 |
| 799 bool use_ic = FLAG_use_ic && !object->IsAccessCheckNeeded(); | |
| 800 if (object->IsJSObject()) { | |
| 801 Handle<JSObject> receiver = Handle<JSObject>::cast(object); | |
| 802 if (receiver->map()->is_deprecated()) { | |
| 803 use_ic = false; | |
| 804 JSObject::MigrateInstance(receiver); | |
| 805 } | |
| 806 } | |
| 807 | |
| 808 if (object->IsUndefined() || object->IsNull()) { | 801 if (object->IsUndefined() || object->IsNull()) { |
| 809 return TypeError("non_object_property_call", object, key); | 802 return TypeError("non_object_property_call", object, key); |
| 810 } | 803 } |
| 811 | 804 |
| 812 ASSERT(!(use_ic && object->IsJSGlobalProxy())); | 805 bool use_ic = MigrateDeprecated(object) |
| 806 ? false : FLAG_use_ic && !object->IsAccessCheckNeeded(); | |
| 813 | 807 |
| 814 if (use_ic && state() != MEGAMORPHIC) { | 808 if (use_ic && state() != MEGAMORPHIC) { |
| 809 ASSERT(!object->IsJSGlobalProxy()); | |
| 815 int argc = target()->arguments_count(); | 810 int argc = target()->arguments_count(); |
| 816 Handle<Code> stub = isolate()->stub_cache()->ComputeCallMegamorphic( | 811 Handle<Code> stub = isolate()->stub_cache()->ComputeCallMegamorphic( |
| 817 argc, Code::KEYED_CALL_IC, Code::kNoExtraICState); | 812 argc, Code::KEYED_CALL_IC, Code::kNoExtraICState); |
| 818 if (object->IsJSObject()) { | 813 if (object->IsJSObject()) { |
| 819 Handle<JSObject> receiver = Handle<JSObject>::cast(object); | 814 Handle<JSObject> receiver = Handle<JSObject>::cast(object); |
| 820 if (receiver->elements()->map() == | 815 if (receiver->elements()->map() == |
| 821 isolate()->heap()->non_strict_arguments_elements_map()) { | 816 isolate()->heap()->non_strict_arguments_elements_map()) { |
| 822 stub = isolate()->stub_cache()->ComputeCallArguments(argc); | 817 stub = isolate()->stub_cache()->ComputeCallArguments(argc); |
| 823 } | 818 } |
| 824 } | 819 } |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 844 | 839 |
| 845 | 840 |
| 846 MaybeObject* LoadIC::Load(Handle<Object> object, | 841 MaybeObject* LoadIC::Load(Handle<Object> object, |
| 847 Handle<String> name) { | 842 Handle<String> name) { |
| 848 // If the object is undefined or null it's illegal to try to get any | 843 // If the object is undefined or null it's illegal to try to get any |
| 849 // of its properties; throw a TypeError in that case. | 844 // of its properties; throw a TypeError in that case. |
| 850 if (object->IsUndefined() || object->IsNull()) { | 845 if (object->IsUndefined() || object->IsNull()) { |
| 851 return TypeError("non_object_property_load", object, name); | 846 return TypeError("non_object_property_load", object, name); |
| 852 } | 847 } |
| 853 | 848 |
| 854 bool use_ic = FLAG_use_ic; | 849 if (FLAG_use_ic) { |
| 855 | |
| 856 if (use_ic) { | |
| 857 // Use specialized code for getting the length of strings and | 850 // Use specialized code for getting the length of strings and |
| 858 // string wrapper objects. The length property of string wrapper | 851 // string wrapper objects. The length property of string wrapper |
| 859 // objects is read-only and therefore always returns the length of | 852 // objects is read-only and therefore always returns the length of |
| 860 // the underlying string value. See ECMA-262 15.5.5.1. | 853 // the underlying string value. See ECMA-262 15.5.5.1. |
| 861 if (object->IsStringWrapper() && | 854 if (object->IsStringWrapper() && |
| 862 name->Equals(isolate()->heap()->length_string())) { | 855 name->Equals(isolate()->heap()->length_string())) { |
| 863 Handle<Code> stub; | 856 Handle<Code> stub; |
| 864 if (state() == UNINITIALIZED) { | 857 if (state() == UNINITIALIZED) { |
| 865 stub = pre_monomorphic_stub(); | 858 stub = pre_monomorphic_stub(); |
| 866 } else if (state() == PREMONOMORPHIC || state() == MONOMORPHIC) { | 859 } else if (state() == PREMONOMORPHIC || state() == MONOMORPHIC) { |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 903 } | 896 } |
| 904 return *Accessors::FunctionGetPrototype(Handle<JSFunction>::cast(object)); | 897 return *Accessors::FunctionGetPrototype(Handle<JSFunction>::cast(object)); |
| 905 } | 898 } |
| 906 } | 899 } |
| 907 | 900 |
| 908 // Check if the name is trivially convertible to an index and get | 901 // Check if the name is trivially convertible to an index and get |
| 909 // the element or char if so. | 902 // the element or char if so. |
| 910 uint32_t index; | 903 uint32_t index; |
| 911 if (kind() == Code::KEYED_LOAD_IC && name->AsArrayIndex(&index)) { | 904 if (kind() == Code::KEYED_LOAD_IC && name->AsArrayIndex(&index)) { |
| 912 // Rewrite to the generic keyed load stub. | 905 // Rewrite to the generic keyed load stub. |
| 913 if (use_ic) set_target(*generic_stub()); | 906 if (FLAG_use_ic) set_target(*generic_stub()); |
| 914 return Runtime::GetElementOrCharAtOrFail(isolate(), object, index); | 907 return Runtime::GetElementOrCharAtOrFail(isolate(), object, index); |
| 915 } | 908 } |
| 916 | 909 |
| 917 if (object->IsJSObject()) { | 910 bool use_ic = MigrateDeprecated(object) ? false : FLAG_use_ic; |
| 918 Handle<JSObject> receiver = Handle<JSObject>::cast(object); | |
| 919 if (receiver->map()->is_deprecated()) { | |
| 920 use_ic = false; | |
| 921 JSObject::MigrateInstance(receiver); | |
| 922 } | |
| 923 } | |
| 924 | 911 |
| 925 // Named lookup in the object. | 912 // Named lookup in the object. |
| 926 LookupResult lookup(isolate()); | 913 LookupResult lookup(isolate()); |
| 927 LookupForRead(object, name, &lookup); | 914 LookupForRead(object, name, &lookup); |
| 928 | 915 |
| 929 // If we did not find a property, check if we need to throw an exception. | 916 // If we did not find a property, check if we need to throw an exception. |
| 930 if (!lookup.IsFound()) { | 917 if (!lookup.IsFound()) { |
| 931 if (IsUndeclaredGlobal(object)) { | 918 if (IsUndeclaredGlobal(object)) { |
| 932 return ReferenceError("not_defined", name); | 919 return ReferenceError("not_defined", name); |
| 933 } | 920 } |
| 934 LOG(isolate(), SuspectReadEvent(*name, *object)); | 921 LOG(isolate(), SuspectReadEvent(*name, *object)); |
| 935 } | 922 } |
| 936 | 923 |
| 937 // Update inline cache and stub cache. | 924 // Update inline cache and stub cache. |
| 938 if (use_ic) UpdateCaches(&lookup, object, name); | 925 if (use_ic) UpdateCaches(&lookup, object, name); |
| 939 | 926 |
| 940 PropertyAttributes attr; | 927 PropertyAttributes attr; |
| 941 if (lookup.IsInterceptor() || lookup.IsHandler()) { | 928 // Get the property. |
| 942 // Get the property. | 929 Handle<Object> result = |
| 943 Handle<Object> result = | 930 Object::GetProperty(object, object, &lookup, name, &attr); |
| 944 Object::GetProperty(object, object, &lookup, name, &attr); | 931 RETURN_IF_EMPTY_HANDLE(isolate(), result); |
| 945 RETURN_IF_EMPTY_HANDLE(isolate(), result); | 932 // If the property is not present, check if we need to throw an |
| 946 // If the property is not present, check if we need to throw an | 933 // exception. |
| 947 // exception. | 934 if ((lookup.IsInterceptor() || lookup.IsHandler()) && |
| 948 if (attr == ABSENT && IsUndeclaredGlobal(object)) { | 935 attr == ABSENT && IsUndeclaredGlobal(object)) { |
| 949 return ReferenceError("not_defined", name); | 936 return ReferenceError("not_defined", name); |
| 950 } | |
| 951 return *result; | |
| 952 } | 937 } |
| 953 | 938 return *result; |
| 954 // Get the property. | |
| 955 return Object::GetPropertyOrFail(object, object, &lookup, name, &attr); | |
| 956 } | 939 } |
| 957 | 940 |
| 958 | 941 |
| 959 static bool AddOneReceiverMapIfMissing(MapHandleList* receiver_maps, | 942 static bool AddOneReceiverMapIfMissing(MapHandleList* receiver_maps, |
| 960 Handle<Map> new_receiver_map) { | 943 Handle<Map> new_receiver_map) { |
| 961 ASSERT(!new_receiver_map.is_null()); | 944 ASSERT(!new_receiver_map.is_null()); |
| 962 for (int current = 0; current < receiver_maps->length(); ++current) { | 945 for (int current = 0; current < receiver_maps->length(); ++current) { |
| 963 if (!receiver_maps->at(current).is_null() && | 946 if (!receiver_maps->at(current).is_null() && |
| 964 receiver_maps->at(current).is_identical_to(new_receiver_map)) { | 947 receiver_maps->at(current).is_identical_to(new_receiver_map)) { |
| 965 return false; | 948 return false; |
| (...skipping 376 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1342 } | 1325 } |
| 1343 | 1326 |
| 1344 return isolate()->stub_cache()->ComputeLoadElementPolymorphic( | 1327 return isolate()->stub_cache()->ComputeLoadElementPolymorphic( |
| 1345 &target_receiver_maps); | 1328 &target_receiver_maps); |
| 1346 } | 1329 } |
| 1347 | 1330 |
| 1348 | 1331 |
| 1349 MaybeObject* KeyedLoadIC::Load(Handle<Object> object, | 1332 MaybeObject* KeyedLoadIC::Load(Handle<Object> object, |
| 1350 Handle<Object> key, | 1333 Handle<Object> key, |
| 1351 ICMissMode miss_mode) { | 1334 ICMissMode miss_mode) { |
| 1335 if (MigrateDeprecated(object)) { | |
| 1336 return Runtime::GetObjectPropertyOrFail(isolate(), object, key); | |
| 1337 } | |
| 1338 | |
| 1352 // Check for values that can be converted into an internalized string directly | 1339 // Check for values that can be converted into an internalized string directly |
| 1353 // or is representable as a smi. | 1340 // or is representable as a smi. |
| 1354 key = TryConvertKey(key, isolate()); | 1341 key = TryConvertKey(key, isolate()); |
| 1355 | 1342 |
| 1356 if (key->IsInternalizedString()) { | 1343 if (key->IsInternalizedString()) { |
| 1357 return LoadIC::Load(object, Handle<String>::cast(key)); | 1344 return LoadIC::Load(object, Handle<String>::cast(key)); |
| 1358 } | 1345 } |
| 1359 | 1346 |
| 1360 bool use_ic = FLAG_use_ic && !object->IsAccessCheckNeeded(); | 1347 if (FLAG_use_ic && !object->IsAccessCheckNeeded()) { |
| 1361 ASSERT(!(use_ic && object->IsJSGlobalProxy())); | 1348 ASSERT(!object->IsJSGlobalProxy()); |
| 1349 Handle<Code> stub = generic_stub(); | |
| 1350 if (miss_mode == MISS_FORCE_GENERIC) { | |
| 1351 TRACE_GENERIC_IC(isolate(), "KeyedLoadIC", "force generic"); | |
| 1352 } else if (object->IsString() && key->IsNumber()) { | |
| 1353 if (state() == UNINITIALIZED) stub = string_stub(); | |
| 1354 } else if (object->IsJSObject()) { | |
| 1355 Handle<JSObject> receiver = Handle<JSObject>::cast(object); | |
| 1356 if (receiver->elements()->map() == | |
| 1357 isolate()->heap()->non_strict_arguments_elements_map()) { | |
| 1358 stub = non_strict_arguments_stub(); | |
| 1359 } else if (receiver->HasIndexedInterceptor()) { | |
| 1360 stub = indexed_interceptor_stub(); | |
| 1361 } else if (!key->ToSmi()->IsFailure() && | |
| 1362 (!target().is_identical_to(non_strict_arguments_stub()))) { | |
| 1363 stub = LoadElementStub(receiver); | |
| 1364 } | |
| 1365 } | |
| 1362 | 1366 |
| 1363 if (use_ic) { | 1367 ASSERT(!stub.is_null()); |
| 1364 Handle<Code> stub = generic_stub(); | 1368 set_target(*stub); |
| 1365 if (miss_mode != MISS_FORCE_GENERIC) { | 1369 TRACE_IC("KeyedLoadIC", key, target()); |
| 1366 if (object->IsString() && key->IsNumber()) { | |
| 1367 if (state() == UNINITIALIZED) { | |
| 1368 stub = string_stub(); | |
| 1369 } | |
| 1370 } else if (object->IsJSObject()) { | |
| 1371 Handle<JSObject> receiver = Handle<JSObject>::cast(object); | |
| 1372 if (receiver->map()->is_deprecated()) { | |
| 1373 use_ic = false; | |
| 1374 JSObject::MigrateInstance(receiver); | |
| 1375 } | |
| 1376 | |
| 1377 if (receiver->elements()->map() == | |
| 1378 isolate()->heap()->non_strict_arguments_elements_map()) { | |
| 1379 stub = non_strict_arguments_stub(); | |
| 1380 } else if (receiver->HasIndexedInterceptor()) { | |
| 1381 stub = indexed_interceptor_stub(); | |
| 1382 } else if (!key->ToSmi()->IsFailure() && | |
| 1383 (!target().is_identical_to(non_strict_arguments_stub()))) { | |
| 1384 stub = LoadElementStub(receiver); | |
| 1385 } | |
| 1386 } | |
| 1387 } else { | |
| 1388 TRACE_GENERIC_IC(isolate(), "KeyedLoadIC", "force generic"); | |
| 1389 } | |
| 1390 if (use_ic) { | |
| 1391 ASSERT(!stub.is_null()); | |
| 1392 set_target(*stub); | |
| 1393 TRACE_IC("KeyedLoadIC", key, target()); | |
| 1394 } | |
| 1395 } | 1370 } |
| 1396 | 1371 |
| 1397 | 1372 |
| 1398 return Runtime::GetObjectPropertyOrFail(isolate(), object, key); | 1373 return Runtime::GetObjectPropertyOrFail(isolate(), object, key); |
| 1399 } | 1374 } |
| 1400 | 1375 |
| 1401 | 1376 |
| 1402 Handle<Code> KeyedLoadIC::ComputeLoadHandler(LookupResult* lookup, | 1377 Handle<Code> KeyedLoadIC::ComputeLoadHandler(LookupResult* lookup, |
| 1403 Handle<JSObject> receiver, | 1378 Handle<JSObject> receiver, |
| 1404 Handle<String> name) { | 1379 Handle<String> name) { |
| (...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1520 ic->MarkMonomorphicPrototypeFailure(); | 1495 ic->MarkMonomorphicPrototypeFailure(); |
| 1521 } | 1496 } |
| 1522 return true; | 1497 return true; |
| 1523 } | 1498 } |
| 1524 | 1499 |
| 1525 | 1500 |
| 1526 MaybeObject* StoreIC::Store(Handle<Object> object, | 1501 MaybeObject* StoreIC::Store(Handle<Object> object, |
| 1527 Handle<String> name, | 1502 Handle<String> name, |
| 1528 Handle<Object> value, | 1503 Handle<Object> value, |
| 1529 JSReceiver::StoreFromKeyed store_mode) { | 1504 JSReceiver::StoreFromKeyed store_mode) { |
| 1530 // Handle proxies. | 1505 // Handle proxies. |
|
ulan
2013/10/02 08:19:25
Update or remove the comment.
| |
| 1531 if (object->IsJSProxy()) { | 1506 if (MigrateDeprecated(object) || object->IsJSProxy()) { |
| 1532 Handle<Object> result = JSReceiver::SetProperty( | 1507 Handle<Object> result = JSReceiver::SetProperty( |
| 1533 Handle<JSReceiver>::cast(object), name, value, NONE, strict_mode()); | 1508 Handle<JSReceiver>::cast(object), name, value, NONE, strict_mode()); |
| 1534 RETURN_IF_EMPTY_HANDLE(isolate(), result); | 1509 RETURN_IF_EMPTY_HANDLE(isolate(), result); |
| 1535 return *result; | 1510 return *result; |
| 1536 } | 1511 } |
| 1537 | 1512 |
| 1538 // If the object is undefined or null it's illegal to try to set any | 1513 // If the object is undefined or null it's illegal to try to set any |
| 1539 // properties on it; throw a TypeError in that case. | 1514 // properties on it; throw a TypeError in that case. |
| 1540 if (object->IsUndefined() || object->IsNull()) { | 1515 if (object->IsUndefined() || object->IsNull()) { |
| 1541 return TypeError("non_object_property_store", object, name); | 1516 return TypeError("non_object_property_store", object, name); |
| 1542 } | 1517 } |
| 1543 | 1518 |
| 1544 // The length property of string values is read-only. Throw in strict mode. | 1519 // The length property of string values is read-only. Throw in strict mode. |
| 1545 if (strict_mode() == kStrictMode && object->IsString() && | 1520 if (strict_mode() == kStrictMode && object->IsString() && |
| 1546 name->Equals(isolate()->heap()->length_string())) { | 1521 name->Equals(isolate()->heap()->length_string())) { |
| 1547 return TypeError("strict_read_only_property", object, name); | 1522 return TypeError("strict_read_only_property", object, name); |
| 1548 } | 1523 } |
| 1549 | 1524 |
| 1550 // Ignore other stores where the receiver is not a JSObject. | 1525 // Ignore other stores where the receiver is not a JSObject. |
| 1551 // TODO(1475): Must check prototype chains of object wrappers. | 1526 // TODO(1475): Must check prototype chains of object wrappers. |
| 1552 if (!object->IsJSObject()) return *value; | 1527 if (!object->IsJSObject()) return *value; |
| 1553 | 1528 |
| 1554 Handle<JSObject> receiver = Handle<JSObject>::cast(object); | 1529 Handle<JSObject> receiver = Handle<JSObject>::cast(object); |
| 1555 | 1530 |
| 1556 bool use_ic = FLAG_use_ic; | |
| 1557 if (receiver->map()->is_deprecated()) { | |
| 1558 use_ic = false; | |
| 1559 JSObject::MigrateInstance(receiver); | |
| 1560 } | |
| 1561 | |
| 1562 // Check if the given name is an array index. | 1531 // Check if the given name is an array index. |
| 1563 uint32_t index; | 1532 uint32_t index; |
| 1564 if (name->AsArrayIndex(&index)) { | 1533 if (name->AsArrayIndex(&index)) { |
| 1565 Handle<Object> result = | 1534 Handle<Object> result = |
| 1566 JSObject::SetElement(receiver, index, value, NONE, strict_mode()); | 1535 JSObject::SetElement(receiver, index, value, NONE, strict_mode()); |
| 1567 RETURN_IF_EMPTY_HANDLE(isolate(), result); | 1536 RETURN_IF_EMPTY_HANDLE(isolate(), result); |
| 1568 return *value; | 1537 return *value; |
| 1569 } | 1538 } |
| 1570 | 1539 |
| 1571 // Observed objects are always modified through the runtime. | 1540 // Observed objects are always modified through the runtime. |
| 1572 if (FLAG_harmony_observation && receiver->map()->is_observed()) { | 1541 if (FLAG_harmony_observation && receiver->map()->is_observed()) { |
| 1573 Handle<Object> result = JSReceiver::SetProperty( | 1542 Handle<Object> result = JSReceiver::SetProperty( |
| 1574 receiver, name, value, NONE, strict_mode(), store_mode); | 1543 receiver, name, value, NONE, strict_mode(), store_mode); |
| 1575 RETURN_IF_EMPTY_HANDLE(isolate(), result); | 1544 RETURN_IF_EMPTY_HANDLE(isolate(), result); |
| 1576 return *result; | 1545 return *result; |
| 1577 } | 1546 } |
| 1578 | 1547 |
| 1579 // Use specialized code for setting the length of arrays with fast | 1548 // Use specialized code for setting the length of arrays with fast |
| 1580 // properties. Slow properties might indicate redefinition of the length | 1549 // properties. Slow properties might indicate redefinition of the length |
| 1581 // property. Note that when redefined using Object.freeze, it's possible | 1550 // property. Note that when redefined using Object.freeze, it's possible |
| 1582 // to have fast properties but a read-only length. | 1551 // to have fast properties but a read-only length. |
| 1583 if (use_ic && | 1552 if (FLAG_use_ic && |
| 1584 receiver->IsJSArray() && | 1553 receiver->IsJSArray() && |
| 1585 name->Equals(isolate()->heap()->length_string()) && | 1554 name->Equals(isolate()->heap()->length_string()) && |
| 1586 Handle<JSArray>::cast(receiver)->AllowsSetElementsLength() && | 1555 Handle<JSArray>::cast(receiver)->AllowsSetElementsLength() && |
| 1587 receiver->HasFastProperties() && | 1556 receiver->HasFastProperties() && |
| 1588 !receiver->map()->is_frozen()) { | 1557 !receiver->map()->is_frozen()) { |
| 1589 Handle<Code> stub = | 1558 Handle<Code> stub = |
| 1590 StoreArrayLengthStub(kind(), strict_mode()).GetCode(isolate()); | 1559 StoreArrayLengthStub(kind(), strict_mode()).GetCode(isolate()); |
| 1591 set_target(*stub); | 1560 set_target(*stub); |
| 1592 TRACE_IC("StoreIC", name, stub); | 1561 TRACE_IC("StoreIC", name, stub); |
| 1593 Handle<Object> result = JSReceiver::SetProperty( | 1562 Handle<Object> result = JSReceiver::SetProperty( |
| 1594 receiver, name, value, NONE, strict_mode(), store_mode); | 1563 receiver, name, value, NONE, strict_mode(), store_mode); |
| 1595 RETURN_IF_EMPTY_HANDLE(isolate(), result); | 1564 RETURN_IF_EMPTY_HANDLE(isolate(), result); |
| 1596 return *result; | 1565 return *result; |
| 1597 } | 1566 } |
| 1598 | 1567 |
| 1599 if (receiver->IsJSGlobalProxy()) { | 1568 if (receiver->IsJSGlobalProxy()) { |
| 1600 if (use_ic && kind() != Code::KEYED_STORE_IC) { | 1569 if (FLAG_use_ic && kind() != Code::KEYED_STORE_IC) { |
| 1601 // Generate a generic stub that goes to the runtime when we see a global | 1570 // Generate a generic stub that goes to the runtime when we see a global |
| 1602 // proxy as receiver. | 1571 // proxy as receiver. |
| 1603 Handle<Code> stub = global_proxy_stub(); | 1572 Handle<Code> stub = global_proxy_stub(); |
| 1604 set_target(*stub); | 1573 set_target(*stub); |
| 1605 TRACE_IC("StoreIC", name, stub); | 1574 TRACE_IC("StoreIC", name, stub); |
| 1606 } | 1575 } |
| 1607 Handle<Object> result = JSReceiver::SetProperty( | 1576 Handle<Object> result = JSReceiver::SetProperty( |
| 1608 receiver, name, value, NONE, strict_mode(), store_mode); | 1577 receiver, name, value, NONE, strict_mode(), store_mode); |
| 1609 RETURN_IF_EMPTY_HANDLE(isolate(), result); | 1578 RETURN_IF_EMPTY_HANDLE(isolate(), result); |
| 1610 return *result; | 1579 return *result; |
| 1611 } | 1580 } |
| 1612 | 1581 |
| 1613 LookupResult lookup(isolate()); | 1582 LookupResult lookup(isolate()); |
| 1614 bool can_store = LookupForWrite(receiver, name, value, &lookup, this); | 1583 bool can_store = LookupForWrite(receiver, name, value, &lookup, this); |
| 1615 if (!can_store && | 1584 if (!can_store && |
| 1616 strict_mode() == kStrictMode && | 1585 strict_mode() == kStrictMode && |
| 1617 !(lookup.IsProperty() && lookup.IsReadOnly()) && | 1586 !(lookup.IsProperty() && lookup.IsReadOnly()) && |
| 1618 IsUndeclaredGlobal(object)) { | 1587 IsUndeclaredGlobal(object)) { |
| 1619 // Strict mode doesn't allow setting non-existent global property. | 1588 // Strict mode doesn't allow setting non-existent global property. |
| 1620 return ReferenceError("not_defined", name); | 1589 return ReferenceError("not_defined", name); |
| 1621 } | 1590 } |
| 1622 if (use_ic) { | 1591 if (FLAG_use_ic) { |
| 1623 if (state() == UNINITIALIZED) { | 1592 if (state() == UNINITIALIZED) { |
| 1624 Handle<Code> stub = pre_monomorphic_stub(); | 1593 Handle<Code> stub = pre_monomorphic_stub(); |
| 1625 set_target(*stub); | 1594 set_target(*stub); |
| 1626 TRACE_IC("StoreIC", name, stub); | 1595 TRACE_IC("StoreIC", name, stub); |
| 1627 } else if (can_store) { | 1596 } else if (can_store) { |
| 1628 UpdateCaches(&lookup, receiver, name, value); | 1597 UpdateCaches(&lookup, receiver, name, value); |
| 1629 } else if (!name->IsCacheable(isolate()) || | 1598 } else if (!name->IsCacheable(isolate()) || |
| 1630 lookup.IsNormal() || | 1599 lookup.IsNormal() || |
| 1631 (lookup.IsField() && lookup.CanHoldValue(value))) { | 1600 (lookup.IsField() && lookup.CanHoldValue(value))) { |
| 1632 Handle<Code> stub = generic_stub(); | 1601 Handle<Code> stub = generic_stub(); |
| (...skipping 354 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1987 return STANDARD_STORE; | 1956 return STANDARD_STORE; |
| 1988 } | 1957 } |
| 1989 } | 1958 } |
| 1990 } | 1959 } |
| 1991 | 1960 |
| 1992 | 1961 |
| 1993 MaybeObject* KeyedStoreIC::Store(Handle<Object> object, | 1962 MaybeObject* KeyedStoreIC::Store(Handle<Object> object, |
| 1994 Handle<Object> key, | 1963 Handle<Object> key, |
| 1995 Handle<Object> value, | 1964 Handle<Object> value, |
| 1996 ICMissMode miss_mode) { | 1965 ICMissMode miss_mode) { |
| 1966 if (MigrateDeprecated(object)) { | |
| 1967 return Runtime::SetObjectPropertyOrFail( | |
| 1968 isolate(), object , key, value, NONE, strict_mode()); | |
| 1969 } | |
| 1970 | |
| 1997 // Check for values that can be converted into an internalized string directly | 1971 // Check for values that can be converted into an internalized string directly |
| 1998 // or is representable as a smi. | 1972 // or is representable as a smi. |
| 1999 key = TryConvertKey(key, isolate()); | 1973 key = TryConvertKey(key, isolate()); |
| 2000 | 1974 |
| 2001 if (key->IsInternalizedString()) { | 1975 if (key->IsInternalizedString()) { |
| 2002 return StoreIC::Store(object, | 1976 return StoreIC::Store(object, |
| 2003 Handle<String>::cast(key), | 1977 Handle<String>::cast(key), |
| 2004 value, | 1978 value, |
| 2005 JSReceiver::MAY_BE_STORE_FROM_KEYED); | 1979 JSReceiver::MAY_BE_STORE_FROM_KEYED); |
| 2006 } | 1980 } |
| 2007 | 1981 |
| 2008 bool use_ic = FLAG_use_ic && !object->IsAccessCheckNeeded() && | 1982 bool use_ic = FLAG_use_ic && !object->IsAccessCheckNeeded() && |
| 2009 !(FLAG_harmony_observation && object->IsJSObject() && | 1983 !(FLAG_harmony_observation && object->IsJSObject() && |
| 2010 JSObject::cast(*object)->map()->is_observed()); | 1984 JSObject::cast(*object)->map()->is_observed()); |
| 2011 if (use_ic && !object->IsSmi()) { | 1985 if (use_ic && !object->IsSmi()) { |
| 2012 // Don't use ICs for maps of the objects in Array's prototype chain. We | 1986 // Don't use ICs for maps of the objects in Array's prototype chain. We |
| 2013 // expect to be able to trap element sets to objects with those maps in the | 1987 // expect to be able to trap element sets to objects with those maps in the |
| 2014 // runtime to enable optimization of element hole access. | 1988 // runtime to enable optimization of element hole access. |
| 2015 Handle<HeapObject> heap_object = Handle<HeapObject>::cast(object); | 1989 Handle<HeapObject> heap_object = Handle<HeapObject>::cast(object); |
| 2016 if (heap_object->map()->IsMapInArrayPrototypeChain()) use_ic = false; | 1990 if (heap_object->map()->IsMapInArrayPrototypeChain()) use_ic = false; |
| 2017 } | 1991 } |
| 2018 ASSERT(!(use_ic && object->IsJSGlobalProxy())); | |
| 2019 | 1992 |
| 2020 if (use_ic) { | 1993 if (use_ic) { |
| 1994 ASSERT(!object->IsJSGlobalProxy()); | |
| 1995 | |
| 2021 Handle<Code> stub = generic_stub(); | 1996 Handle<Code> stub = generic_stub(); |
| 2022 if (miss_mode != MISS_FORCE_GENERIC) { | 1997 if (miss_mode != MISS_FORCE_GENERIC) { |
| 2023 if (object->IsJSObject()) { | 1998 if (object->IsJSObject()) { |
| 2024 Handle<JSObject> receiver = Handle<JSObject>::cast(object); | 1999 Handle<JSObject> receiver = Handle<JSObject>::cast(object); |
| 2025 if (receiver->map()->is_deprecated()) { | |
| 2026 JSObject::MigrateInstance(receiver); | |
| 2027 } | |
| 2028 bool key_is_smi_like = key->IsSmi() || !key->ToSmi()->IsFailure(); | 2000 bool key_is_smi_like = key->IsSmi() || !key->ToSmi()->IsFailure(); |
| 2029 if (receiver->elements()->map() == | 2001 if (receiver->elements()->map() == |
| 2030 isolate()->heap()->non_strict_arguments_elements_map()) { | 2002 isolate()->heap()->non_strict_arguments_elements_map()) { |
| 2031 stub = non_strict_arguments_stub(); | 2003 stub = non_strict_arguments_stub(); |
| 2032 } else if (key_is_smi_like && | 2004 } else if (key_is_smi_like && |
| 2033 (!target().is_identical_to(non_strict_arguments_stub()))) { | 2005 (!target().is_identical_to(non_strict_arguments_stub()))) { |
| 2034 KeyedAccessStoreMode store_mode = GetStoreMode(receiver, key, value); | 2006 KeyedAccessStoreMode store_mode = GetStoreMode(receiver, key, value); |
| 2035 stub = StoreElementStub(receiver, store_mode); | 2007 stub = StoreElementStub(receiver, store_mode); |
| 2036 } else { | 2008 } else { |
| 2037 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "key not a number"); | 2009 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "key not a number"); |
| (...skipping 929 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2967 #undef ADDR | 2939 #undef ADDR |
| 2968 }; | 2940 }; |
| 2969 | 2941 |
| 2970 | 2942 |
| 2971 Address IC::AddressFromUtilityId(IC::UtilityId id) { | 2943 Address IC::AddressFromUtilityId(IC::UtilityId id) { |
| 2972 return IC_utilities[id]; | 2944 return IC_utilities[id]; |
| 2973 } | 2945 } |
| 2974 | 2946 |
| 2975 | 2947 |
| 2976 } } // namespace v8::internal | 2948 } } // namespace v8::internal |
| OLD | NEW |