| OLD | NEW |
| 1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 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 501 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 512 MaybeObject* maybe = GetHeap()->Uint32ToString(index); | 512 MaybeObject* maybe = GetHeap()->Uint32ToString(index); |
| 513 if (!maybe->To<String>(&name)) return maybe; | 513 if (!maybe->To<String>(&name)) return maybe; |
| 514 return GetPropertyWithHandler(receiver, name); | 514 return GetPropertyWithHandler(receiver, name); |
| 515 } | 515 } |
| 516 | 516 |
| 517 | 517 |
| 518 Handle<Object> JSProxy::SetElementWithHandler(Handle<JSProxy> proxy, | 518 Handle<Object> JSProxy::SetElementWithHandler(Handle<JSProxy> proxy, |
| 519 Handle<JSReceiver> receiver, | 519 Handle<JSReceiver> receiver, |
| 520 uint32_t index, | 520 uint32_t index, |
| 521 Handle<Object> value, | 521 Handle<Object> value, |
| 522 StrictModeFlag strict_mode) { | 522 StrictMode strict_mode) { |
| 523 Isolate* isolate = proxy->GetIsolate(); | 523 Isolate* isolate = proxy->GetIsolate(); |
| 524 Handle<String> name = isolate->factory()->Uint32ToString(index); | 524 Handle<String> name = isolate->factory()->Uint32ToString(index); |
| 525 return SetPropertyWithHandler( | 525 return SetPropertyWithHandler( |
| 526 proxy, receiver, name, value, NONE, strict_mode); | 526 proxy, receiver, name, value, NONE, strict_mode); |
| 527 } | 527 } |
| 528 | 528 |
| 529 | 529 |
| 530 bool JSProxy::HasElementWithHandler(Handle<JSProxy> proxy, uint32_t index) { | 530 bool JSProxy::HasElementWithHandler(Handle<JSProxy> proxy, uint32_t index) { |
| 531 Isolate* isolate = proxy->GetIsolate(); | 531 Isolate* isolate = proxy->GetIsolate(); |
| 532 Handle<String> name = isolate->factory()->Uint32ToString(index); | 532 Handle<String> name = isolate->factory()->Uint32ToString(index); |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 608 } | 608 } |
| 609 break; | 609 break; |
| 610 } | 610 } |
| 611 default: | 611 default: |
| 612 UNREACHABLE(); | 612 UNREACHABLE(); |
| 613 } | 613 } |
| 614 } | 614 } |
| 615 | 615 |
| 616 // No accessible property found. | 616 // No accessible property found. |
| 617 *attributes = ABSENT; | 617 *attributes = ABSENT; |
| 618 isolate->ReportFailedAccessCheck(*object, v8::ACCESS_GET); | 618 isolate->ReportFailedAccessCheckWrapper(object, v8::ACCESS_GET); |
| 619 RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object); | 619 RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object); |
| 620 return isolate->factory()->undefined_value(); | 620 return isolate->factory()->undefined_value(); |
| 621 } | 621 } |
| 622 | 622 |
| 623 | 623 |
| 624 PropertyAttributes JSObject::GetPropertyAttributeWithFailedAccessCheck( | 624 PropertyAttributes JSObject::GetPropertyAttributeWithFailedAccessCheck( |
| 625 Object* receiver, | 625 Handle<JSObject> object, |
| 626 LookupResult* result, | 626 LookupResult* result, |
| 627 Name* name, | 627 Handle<Name> name, |
| 628 bool continue_search) { | 628 bool continue_search) { |
| 629 if (result->IsProperty()) { | 629 if (result->IsProperty()) { |
| 630 switch (result->type()) { | 630 switch (result->type()) { |
| 631 case CALLBACKS: { | 631 case CALLBACKS: { |
| 632 // Only allow API accessors. | 632 // Only allow API accessors. |
| 633 Object* obj = result->GetCallbackObject(); | 633 Handle<Object> obj(result->GetCallbackObject(), object->GetIsolate()); |
| 634 if (obj->IsAccessorInfo()) { | 634 if (obj->IsAccessorInfo()) { |
| 635 AccessorInfo* info = AccessorInfo::cast(obj); | 635 Handle<AccessorInfo> info = Handle<AccessorInfo>::cast(obj); |
| 636 if (info->all_can_read()) { | 636 if (info->all_can_read()) { |
| 637 return result->GetAttributes(); | 637 return result->GetAttributes(); |
| 638 } | 638 } |
| 639 } else if (obj->IsAccessorPair()) { | 639 } else if (obj->IsAccessorPair()) { |
| 640 AccessorPair* pair = AccessorPair::cast(obj); | 640 Handle<AccessorPair> pair = Handle<AccessorPair>::cast(obj); |
| 641 if (pair->all_can_read()) { | 641 if (pair->all_can_read()) { |
| 642 return result->GetAttributes(); | 642 return result->GetAttributes(); |
| 643 } | 643 } |
| 644 } | 644 } |
| 645 break; | 645 break; |
| 646 } | 646 } |
| 647 | 647 |
| 648 case NORMAL: | 648 case NORMAL: |
| 649 case FIELD: | 649 case FIELD: |
| 650 case CONSTANT: { | 650 case CONSTANT: { |
| 651 if (!continue_search) break; | 651 if (!continue_search) break; |
| 652 // Search ALL_CAN_READ accessors in prototype chain. | 652 // Search ALL_CAN_READ accessors in prototype chain. |
| 653 LookupResult r(GetIsolate()); | 653 LookupResult r(object->GetIsolate()); |
| 654 result->holder()->LookupRealNamedPropertyInPrototypes(name, &r); | 654 result->holder()->LookupRealNamedPropertyInPrototypes(*name, &r); |
| 655 if (r.IsProperty()) { | 655 if (r.IsProperty()) { |
| 656 return GetPropertyAttributeWithFailedAccessCheck(receiver, | 656 return GetPropertyAttributeWithFailedAccessCheck( |
| 657 &r, | 657 object, &r, name, continue_search); |
| 658 name, | |
| 659 continue_search); | |
| 660 } | 658 } |
| 661 break; | 659 break; |
| 662 } | 660 } |
| 663 | 661 |
| 664 case INTERCEPTOR: { | 662 case INTERCEPTOR: { |
| 665 // If the object has an interceptor, try real named properties. | 663 // If the object has an interceptor, try real named properties. |
| 666 // No access check in GetPropertyAttributeWithInterceptor. | 664 // No access check in GetPropertyAttributeWithInterceptor. |
| 667 LookupResult r(GetIsolate()); | 665 LookupResult r(object->GetIsolate()); |
| 668 if (continue_search) { | 666 if (continue_search) { |
| 669 result->holder()->LookupRealNamedProperty(name, &r); | 667 result->holder()->LookupRealNamedProperty(*name, &r); |
| 670 } else { | 668 } else { |
| 671 result->holder()->LocalLookupRealNamedProperty(name, &r); | 669 result->holder()->LocalLookupRealNamedProperty(*name, &r); |
| 672 } | 670 } |
| 673 if (!r.IsFound()) break; | 671 if (!r.IsFound()) break; |
| 674 return GetPropertyAttributeWithFailedAccessCheck(receiver, | 672 return GetPropertyAttributeWithFailedAccessCheck( |
| 675 &r, | 673 object, &r, name, continue_search); |
| 676 name, | |
| 677 continue_search); | |
| 678 } | 674 } |
| 679 | 675 |
| 680 case HANDLER: | 676 case HANDLER: |
| 681 case TRANSITION: | 677 case TRANSITION: |
| 682 case NONEXISTENT: | 678 case NONEXISTENT: |
| 683 UNREACHABLE(); | 679 UNREACHABLE(); |
| 684 } | 680 } |
| 685 } | 681 } |
| 686 | 682 |
| 687 GetIsolate()->ReportFailedAccessCheck(this, v8::ACCESS_HAS); | 683 object->GetIsolate()->ReportFailedAccessCheckWrapper(object, v8::ACCESS_HAS); |
| 688 return ABSENT; | 684 return ABSENT; |
| 689 } | 685 } |
| 690 | 686 |
| 691 | 687 |
| 692 Object* JSObject::GetNormalizedProperty(const LookupResult* result) { | 688 Object* JSObject::GetNormalizedProperty(const LookupResult* result) { |
| 693 ASSERT(!HasFastProperties()); | 689 ASSERT(!HasFastProperties()); |
| 694 Object* value = property_dictionary()->ValueAt(result->GetDictionaryEntry()); | 690 Object* value = property_dictionary()->ValueAt(result->GetDictionaryEntry()); |
| 695 if (IsGlobalObject()) { | 691 if (IsGlobalObject()) { |
| 696 value = PropertyCell::cast(value)->value(); | 692 value = PropertyCell::cast(value)->value(); |
| 697 } | 693 } |
| (...skipping 575 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1273 return false; | 1269 return false; |
| 1274 } | 1270 } |
| 1275 bool is_ascii = this->IsOneByteRepresentation(); | 1271 bool is_ascii = this->IsOneByteRepresentation(); |
| 1276 bool is_internalized = this->IsInternalizedString(); | 1272 bool is_internalized = this->IsInternalizedString(); |
| 1277 | 1273 |
| 1278 // Morph the string to an external string by replacing the map and | 1274 // Morph the string to an external string by replacing the map and |
| 1279 // reinitializing the fields. This won't work if | 1275 // reinitializing the fields. This won't work if |
| 1280 // - the space the existing string occupies is too small for a regular | 1276 // - the space the existing string occupies is too small for a regular |
| 1281 // external string. | 1277 // external string. |
| 1282 // - the existing string is in old pointer space and the backing store of | 1278 // - the existing string is in old pointer space and the backing store of |
| 1283 // the external string is not aligned. The GC cannot deal with fields | 1279 // the external string is not aligned. The GC cannot deal with a field |
| 1284 // containing an unaligned address that points to outside of V8's heap. | 1280 // containing a possibly unaligned address to outside of V8's heap. |
| 1285 // In either case we resort to a short external string instead, omitting | 1281 // In either case we resort to a short external string instead, omitting |
| 1286 // the field caching the address of the backing store. When we encounter | 1282 // the field caching the address of the backing store. When we encounter |
| 1287 // short external strings in generated code, we need to bailout to runtime. | 1283 // short external strings in generated code, we need to bailout to runtime. |
| 1288 if (size < ExternalString::kSize || | 1284 if (size < ExternalString::kSize || |
| 1289 (!IsAligned(reinterpret_cast<intptr_t>(resource->data()), kPointerSize) && | 1285 heap->old_pointer_space()->Contains(this)) { |
| 1290 heap->old_pointer_space()->Contains(this))) { | |
| 1291 this->set_map_no_write_barrier( | 1286 this->set_map_no_write_barrier( |
| 1292 is_internalized | 1287 is_internalized |
| 1293 ? (is_ascii | 1288 ? (is_ascii |
| 1294 ? heap-> | 1289 ? heap-> |
| 1295 short_external_internalized_string_with_one_byte_data_map() | 1290 short_external_internalized_string_with_one_byte_data_map() |
| 1296 : heap->short_external_internalized_string_map()) | 1291 : heap->short_external_internalized_string_map()) |
| 1297 : (is_ascii | 1292 : (is_ascii |
| 1298 ? heap->short_external_string_with_one_byte_data_map() | 1293 ? heap->short_external_string_with_one_byte_data_map() |
| 1299 : heap->short_external_string_map())); | 1294 : heap->short_external_string_map())); |
| 1300 } else { | 1295 } else { |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1344 if (size < ExternalString::kShortSize) { | 1339 if (size < ExternalString::kShortSize) { |
| 1345 return false; | 1340 return false; |
| 1346 } | 1341 } |
| 1347 bool is_internalized = this->IsInternalizedString(); | 1342 bool is_internalized = this->IsInternalizedString(); |
| 1348 | 1343 |
| 1349 // Morph the string to an external string by replacing the map and | 1344 // Morph the string to an external string by replacing the map and |
| 1350 // reinitializing the fields. This won't work if | 1345 // reinitializing the fields. This won't work if |
| 1351 // - the space the existing string occupies is too small for a regular | 1346 // - the space the existing string occupies is too small for a regular |
| 1352 // external string. | 1347 // external string. |
| 1353 // - the existing string is in old pointer space and the backing store of | 1348 // - the existing string is in old pointer space and the backing store of |
| 1354 // the external string is not aligned. The GC cannot deal with fields | 1349 // the external string is not aligned. The GC cannot deal with a field |
| 1355 // containing an unaligned address that points to outside of V8's heap. | 1350 // containing a possibly unaligned address to outside of V8's heap. |
| 1356 // In either case we resort to a short external string instead, omitting | 1351 // In either case we resort to a short external string instead, omitting |
| 1357 // the field caching the address of the backing store. When we encounter | 1352 // the field caching the address of the backing store. When we encounter |
| 1358 // short external strings in generated code, we need to bailout to runtime. | 1353 // short external strings in generated code, we need to bailout to runtime. |
| 1359 if (size < ExternalString::kSize || | 1354 if (size < ExternalString::kSize || |
| 1360 (!IsAligned(reinterpret_cast<intptr_t>(resource->data()), kPointerSize) && | 1355 heap->old_pointer_space()->Contains(this)) { |
| 1361 heap->old_pointer_space()->Contains(this))) { | |
| 1362 this->set_map_no_write_barrier( | 1356 this->set_map_no_write_barrier( |
| 1363 is_internalized ? heap->short_external_ascii_internalized_string_map() | 1357 is_internalized ? heap->short_external_ascii_internalized_string_map() |
| 1364 : heap->short_external_ascii_string_map()); | 1358 : heap->short_external_ascii_string_map()); |
| 1365 } else { | 1359 } else { |
| 1366 this->set_map_no_write_barrier( | 1360 this->set_map_no_write_barrier( |
| 1367 is_internalized ? heap->external_ascii_internalized_string_map() | 1361 is_internalized ? heap->external_ascii_internalized_string_map() |
| 1368 : heap->external_ascii_string_map()); | 1362 : heap->external_ascii_string_map()); |
| 1369 } | 1363 } |
| 1370 ExternalAsciiString* self = ExternalAsciiString::cast(this); | 1364 ExternalAsciiString* self = ExternalAsciiString::cast(this); |
| 1371 self->set_resource(resource); | 1365 self->set_resource(resource); |
| (...skipping 598 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1970 static Handle<Object> NewStorageFor(Isolate* isolate, | 1964 static Handle<Object> NewStorageFor(Isolate* isolate, |
| 1971 Handle<Object> object, | 1965 Handle<Object> object, |
| 1972 Representation representation) { | 1966 Representation representation) { |
| 1973 Heap* heap = isolate->heap(); | 1967 Heap* heap = isolate->heap(); |
| 1974 CALL_HEAP_FUNCTION(isolate, | 1968 CALL_HEAP_FUNCTION(isolate, |
| 1975 object->AllocateNewStorageFor(heap, representation), | 1969 object->AllocateNewStorageFor(heap, representation), |
| 1976 Object); | 1970 Object); |
| 1977 } | 1971 } |
| 1978 | 1972 |
| 1979 | 1973 |
| 1980 void JSObject::AddFastPropertyUsingMap(Handle<JSObject> object, | |
| 1981 Handle<Map> new_map, | |
| 1982 Handle<Name> name, | |
| 1983 Handle<Object> value, | |
| 1984 int field_index, | |
| 1985 Representation representation) { | |
| 1986 Isolate* isolate = object->GetIsolate(); | |
| 1987 | |
| 1988 // This method is used to transition to a field. If we are transitioning to a | |
| 1989 // double field, allocate new storage. | |
| 1990 Handle<Object> storage = NewStorageFor(isolate, value, representation); | |
| 1991 | |
| 1992 if (object->map()->unused_property_fields() == 0) { | |
| 1993 int new_unused = new_map->unused_property_fields(); | |
| 1994 Handle<FixedArray> properties(object->properties()); | |
| 1995 Handle<FixedArray> values = isolate->factory()->CopySizeFixedArray( | |
| 1996 properties, properties->length() + new_unused + 1); | |
| 1997 object->set_properties(*values); | |
| 1998 } | |
| 1999 | |
| 2000 object->set_map(*new_map); | |
| 2001 object->FastPropertyAtPut(field_index, *storage); | |
| 2002 } | |
| 2003 | |
| 2004 | |
| 2005 static MaybeObject* CopyAddFieldDescriptor(Map* map, | 1974 static MaybeObject* CopyAddFieldDescriptor(Map* map, |
| 2006 Name* name, | 1975 Name* name, |
| 2007 int index, | 1976 int index, |
| 2008 PropertyAttributes attributes, | 1977 PropertyAttributes attributes, |
| 2009 Representation representation, | 1978 Representation representation, |
| 2010 TransitionFlag flag) { | 1979 TransitionFlag flag) { |
| 2011 Map* new_map; | 1980 Map* new_map; |
| 2012 FieldDescriptor new_field_desc(name, index, attributes, representation); | 1981 FieldDescriptor new_field_desc(name, index, attributes, representation); |
| 2013 MaybeObject* maybe_map = map->CopyAddDescriptor(&new_field_desc, flag); | 1982 MaybeObject* maybe_map = map->CopyAddDescriptor(&new_field_desc, flag); |
| 2014 if (!maybe_map->To(&new_map)) return maybe_map; | 1983 if (!maybe_map->To(&new_map)) return maybe_map; |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2059 | 2028 |
| 2060 // Compute the new index for new field. | 2029 // Compute the new index for new field. |
| 2061 int index = object->map()->NextFreePropertyIndex(); | 2030 int index = object->map()->NextFreePropertyIndex(); |
| 2062 | 2031 |
| 2063 // Allocate new instance descriptors with (name, index) added | 2032 // Allocate new instance descriptors with (name, index) added |
| 2064 if (object->IsJSContextExtensionObject()) value_type = FORCE_TAGGED; | 2033 if (object->IsJSContextExtensionObject()) value_type = FORCE_TAGGED; |
| 2065 Representation representation = value->OptimalRepresentation(value_type); | 2034 Representation representation = value->OptimalRepresentation(value_type); |
| 2066 Handle<Map> new_map = CopyAddFieldDescriptor( | 2035 Handle<Map> new_map = CopyAddFieldDescriptor( |
| 2067 handle(object->map()), name, index, attributes, representation, flag); | 2036 handle(object->map()), name, index, attributes, representation, flag); |
| 2068 | 2037 |
| 2069 AddFastPropertyUsingMap(object, new_map, name, value, index, representation); | 2038 JSObject::MigrateToMap(object, new_map); |
| 2039 |
| 2040 if (representation.IsDouble()) { |
| 2041 // Nothing more to be done. |
| 2042 if (value->IsUninitialized()) return; |
| 2043 HeapNumber* box = HeapNumber::cast(object->RawFastPropertyAt(index)); |
| 2044 box->set_value(value->Number()); |
| 2045 } else { |
| 2046 object->FastPropertyAtPut(index, *value); |
| 2047 } |
| 2070 } | 2048 } |
| 2071 | 2049 |
| 2072 | 2050 |
| 2073 static MaybeObject* CopyAddConstantDescriptor(Map* map, | 2051 static MaybeObject* CopyAddConstantDescriptor(Map* map, |
| 2074 Name* name, | 2052 Name* name, |
| 2075 Object* value, | 2053 Object* value, |
| 2076 PropertyAttributes attributes, | 2054 PropertyAttributes attributes, |
| 2077 TransitionFlag flag) { | 2055 TransitionFlag flag) { |
| 2078 ConstantDescriptor new_constant_desc(name, value, attributes); | 2056 ConstantDescriptor new_constant_desc(name, value, attributes); |
| 2079 return map->CopyAddDescriptor(&new_constant_desc, flag); | 2057 return map->CopyAddDescriptor(&new_constant_desc, flag); |
| (...skipping 23 matching lines...) Expand all Loading... |
| 2103 // Don't add transitions to special properties with non-trivial | 2081 // Don't add transitions to special properties with non-trivial |
| 2104 // attributes. | 2082 // attributes. |
| 2105 attributes != NONE) | 2083 attributes != NONE) |
| 2106 ? OMIT_TRANSITION | 2084 ? OMIT_TRANSITION |
| 2107 : initial_flag; | 2085 : initial_flag; |
| 2108 | 2086 |
| 2109 // Allocate new instance descriptors with (name, constant) added. | 2087 // Allocate new instance descriptors with (name, constant) added. |
| 2110 Handle<Map> new_map = CopyAddConstantDescriptor( | 2088 Handle<Map> new_map = CopyAddConstantDescriptor( |
| 2111 handle(object->map()), name, constant, attributes, flag); | 2089 handle(object->map()), name, constant, attributes, flag); |
| 2112 | 2090 |
| 2113 object->set_map(*new_map); | 2091 JSObject::MigrateToMap(object, new_map); |
| 2114 } | 2092 } |
| 2115 | 2093 |
| 2116 | 2094 |
| 2117 void JSObject::AddSlowProperty(Handle<JSObject> object, | 2095 void JSObject::AddSlowProperty(Handle<JSObject> object, |
| 2118 Handle<Name> name, | 2096 Handle<Name> name, |
| 2119 Handle<Object> value, | 2097 Handle<Object> value, |
| 2120 PropertyAttributes attributes) { | 2098 PropertyAttributes attributes) { |
| 2121 ASSERT(!object->HasFastProperties()); | 2099 ASSERT(!object->HasFastProperties()); |
| 2122 Isolate* isolate = object->GetIsolate(); | 2100 Isolate* isolate = object->GetIsolate(); |
| 2123 Handle<NameDictionary> dict(object->property_dictionary()); | 2101 Handle<NameDictionary> dict(object->property_dictionary()); |
| (...skipping 18 matching lines...) Expand all Loading... |
| 2142 PropertyDetails details = PropertyDetails(attributes, NORMAL, 0); | 2120 PropertyDetails details = PropertyDetails(attributes, NORMAL, 0); |
| 2143 Handle<NameDictionary> result = NameDictionaryAdd(dict, name, value, details); | 2121 Handle<NameDictionary> result = NameDictionaryAdd(dict, name, value, details); |
| 2144 if (*dict != *result) object->set_properties(*result); | 2122 if (*dict != *result) object->set_properties(*result); |
| 2145 } | 2123 } |
| 2146 | 2124 |
| 2147 | 2125 |
| 2148 Handle<Object> JSObject::AddProperty(Handle<JSObject> object, | 2126 Handle<Object> JSObject::AddProperty(Handle<JSObject> object, |
| 2149 Handle<Name> name, | 2127 Handle<Name> name, |
| 2150 Handle<Object> value, | 2128 Handle<Object> value, |
| 2151 PropertyAttributes attributes, | 2129 PropertyAttributes attributes, |
| 2152 StrictModeFlag strict_mode, | 2130 StrictMode strict_mode, |
| 2153 JSReceiver::StoreFromKeyed store_mode, | 2131 JSReceiver::StoreFromKeyed store_mode, |
| 2154 ExtensibilityCheck extensibility_check, | 2132 ExtensibilityCheck extensibility_check, |
| 2155 ValueType value_type, | 2133 ValueType value_type, |
| 2156 StoreMode mode, | 2134 StoreMode mode, |
| 2157 TransitionFlag transition_flag) { | 2135 TransitionFlag transition_flag) { |
| 2158 ASSERT(!object->IsJSGlobalProxy()); | 2136 ASSERT(!object->IsJSGlobalProxy()); |
| 2159 Isolate* isolate = object->GetIsolate(); | 2137 Isolate* isolate = object->GetIsolate(); |
| 2160 | 2138 |
| 2161 if (!name->IsUniqueName()) { | 2139 if (!name->IsUniqueName()) { |
| 2162 name = isolate->factory()->InternalizeString( | 2140 name = isolate->factory()->InternalizeString( |
| 2163 Handle<String>::cast(name)); | 2141 Handle<String>::cast(name)); |
| 2164 } | 2142 } |
| 2165 | 2143 |
| 2166 if (extensibility_check == PERFORM_EXTENSIBILITY_CHECK && | 2144 if (extensibility_check == PERFORM_EXTENSIBILITY_CHECK && |
| 2167 !object->map()->is_extensible()) { | 2145 !object->map()->is_extensible()) { |
| 2168 if (strict_mode == kNonStrictMode) { | 2146 if (strict_mode == SLOPPY) { |
| 2169 return value; | 2147 return value; |
| 2170 } else { | 2148 } else { |
| 2171 Handle<Object> args[1] = { name }; | 2149 Handle<Object> args[1] = { name }; |
| 2172 Handle<Object> error = isolate->factory()->NewTypeError( | 2150 Handle<Object> error = isolate->factory()->NewTypeError( |
| 2173 "object_not_extensible", HandleVector(args, ARRAY_SIZE(args))); | 2151 "object_not_extensible", HandleVector(args, ARRAY_SIZE(args))); |
| 2174 isolate->Throw(*error); | 2152 isolate->Throw(*error); |
| 2175 return Handle<Object>(); | 2153 return Handle<Object>(); |
| 2176 } | 2154 } |
| 2177 } | 2155 } |
| 2178 | 2156 |
| (...skipping 13 matching lines...) Expand all Loading... |
| 2192 } else { | 2170 } else { |
| 2193 // Normalize the object to prevent very large instance descriptors. | 2171 // Normalize the object to prevent very large instance descriptors. |
| 2194 // This eliminates unwanted N^2 allocation and lookup behavior. | 2172 // This eliminates unwanted N^2 allocation and lookup behavior. |
| 2195 NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0); | 2173 NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0); |
| 2196 AddSlowProperty(object, name, value, attributes); | 2174 AddSlowProperty(object, name, value, attributes); |
| 2197 } | 2175 } |
| 2198 } else { | 2176 } else { |
| 2199 AddSlowProperty(object, name, value, attributes); | 2177 AddSlowProperty(object, name, value, attributes); |
| 2200 } | 2178 } |
| 2201 | 2179 |
| 2202 if (FLAG_harmony_observation && | 2180 if (object->map()->is_observed() && |
| 2203 object->map()->is_observed() && | |
| 2204 *name != isolate->heap()->hidden_string()) { | 2181 *name != isolate->heap()->hidden_string()) { |
| 2205 Handle<Object> old_value = isolate->factory()->the_hole_value(); | 2182 Handle<Object> old_value = isolate->factory()->the_hole_value(); |
| 2206 EnqueueChangeRecord(object, "add", name, old_value); | 2183 EnqueueChangeRecord(object, "add", name, old_value); |
| 2207 } | 2184 } |
| 2208 | 2185 |
| 2209 return value; | 2186 return value; |
| 2210 } | 2187 } |
| 2211 | 2188 |
| 2212 | 2189 |
| 2213 void JSObject::EnqueueChangeRecord(Handle<JSObject> object, | 2190 void JSObject::EnqueueChangeRecord(Handle<JSObject> object, |
| (...skipping 17 matching lines...) Expand all Loading... |
| 2231 &threw); | 2208 &threw); |
| 2232 ASSERT(!threw); | 2209 ASSERT(!threw); |
| 2233 } | 2210 } |
| 2234 | 2211 |
| 2235 | 2212 |
| 2236 Handle<Object> JSObject::SetPropertyPostInterceptor( | 2213 Handle<Object> JSObject::SetPropertyPostInterceptor( |
| 2237 Handle<JSObject> object, | 2214 Handle<JSObject> object, |
| 2238 Handle<Name> name, | 2215 Handle<Name> name, |
| 2239 Handle<Object> value, | 2216 Handle<Object> value, |
| 2240 PropertyAttributes attributes, | 2217 PropertyAttributes attributes, |
| 2241 StrictModeFlag strict_mode) { | 2218 StrictMode strict_mode) { |
| 2242 // Check local property, ignore interceptor. | 2219 // Check local property, ignore interceptor. |
| 2243 LookupResult result(object->GetIsolate()); | 2220 LookupResult result(object->GetIsolate()); |
| 2244 object->LocalLookupRealNamedProperty(*name, &result); | 2221 object->LocalLookupRealNamedProperty(*name, &result); |
| 2245 if (!result.IsFound()) { | 2222 if (!result.IsFound()) { |
| 2246 object->map()->LookupTransition(*object, *name, &result); | 2223 object->map()->LookupTransition(*object, *name, &result); |
| 2247 } | 2224 } |
| 2248 if (result.IsFound()) { | 2225 if (result.IsFound()) { |
| 2249 // An existing property or a map transition was found. Use set property to | 2226 // An existing property or a map transition was found. Use set property to |
| 2250 // handle all these cases. | 2227 // handle all these cases. |
| 2251 return SetPropertyForResult(object, &result, name, value, attributes, | 2228 return SetPropertyForResult(object, &result, name, value, attributes, |
| (...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2351 | 2328 |
| 2352 bool Map::InstancesNeedRewriting(Map* target, | 2329 bool Map::InstancesNeedRewriting(Map* target, |
| 2353 int target_number_of_fields, | 2330 int target_number_of_fields, |
| 2354 int target_inobject, | 2331 int target_inobject, |
| 2355 int target_unused) { | 2332 int target_unused) { |
| 2356 // If fields were added (or removed), rewrite the instance. | 2333 // If fields were added (or removed), rewrite the instance. |
| 2357 int number_of_fields = NumberOfFields(); | 2334 int number_of_fields = NumberOfFields(); |
| 2358 ASSERT(target_number_of_fields >= number_of_fields); | 2335 ASSERT(target_number_of_fields >= number_of_fields); |
| 2359 if (target_number_of_fields != number_of_fields) return true; | 2336 if (target_number_of_fields != number_of_fields) return true; |
| 2360 | 2337 |
| 2361 if (FLAG_track_double_fields) { | 2338 // If smi descriptors were replaced by double descriptors, rewrite. |
| 2362 // If smi descriptors were replaced by double descriptors, rewrite. | 2339 DescriptorArray* old_desc = instance_descriptors(); |
| 2363 DescriptorArray* old_desc = instance_descriptors(); | 2340 DescriptorArray* new_desc = target->instance_descriptors(); |
| 2364 DescriptorArray* new_desc = target->instance_descriptors(); | 2341 int limit = NumberOfOwnDescriptors(); |
| 2365 int limit = NumberOfOwnDescriptors(); | 2342 for (int i = 0; i < limit; i++) { |
| 2366 for (int i = 0; i < limit; i++) { | 2343 if (new_desc->GetDetails(i).representation().IsDouble() && |
| 2367 if (new_desc->GetDetails(i).representation().IsDouble() && | 2344 !old_desc->GetDetails(i).representation().IsDouble()) { |
| 2368 !old_desc->GetDetails(i).representation().IsDouble()) { | 2345 return true; |
| 2369 return true; | |
| 2370 } | |
| 2371 } | 2346 } |
| 2372 } | 2347 } |
| 2373 | 2348 |
| 2374 // If no fields were added, and no inobject properties were removed, setting | 2349 // If no fields were added, and no inobject properties were removed, setting |
| 2375 // the map is sufficient. | 2350 // the map is sufficient. |
| 2376 if (target_inobject == inobject_properties()) return false; | 2351 if (target_inobject == inobject_properties()) return false; |
| 2377 // In-object slack tracking may have reduced the object size of the new map. | 2352 // In-object slack tracking may have reduced the object size of the new map. |
| 2378 // In that case, succeed if all existing fields were inobject, and they still | 2353 // In that case, succeed if all existing fields were inobject, and they still |
| 2379 // fit within the new inobject size. | 2354 // fit within the new inobject size. |
| 2380 ASSERT(target_inobject < inobject_properties()); | 2355 ASSERT(target_inobject < inobject_properties()); |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2416 object->set_map(*new_map); | 2391 object->set_map(*new_map); |
| 2417 return; | 2392 return; |
| 2418 } | 2393 } |
| 2419 | 2394 |
| 2420 int total_size = number_of_fields + unused; | 2395 int total_size = number_of_fields + unused; |
| 2421 int external = total_size - inobject; | 2396 int external = total_size - inobject; |
| 2422 Handle<FixedArray> array = isolate->factory()->NewFixedArray(total_size); | 2397 Handle<FixedArray> array = isolate->factory()->NewFixedArray(total_size); |
| 2423 | 2398 |
| 2424 Handle<DescriptorArray> old_descriptors(old_map->instance_descriptors()); | 2399 Handle<DescriptorArray> old_descriptors(old_map->instance_descriptors()); |
| 2425 Handle<DescriptorArray> new_descriptors(new_map->instance_descriptors()); | 2400 Handle<DescriptorArray> new_descriptors(new_map->instance_descriptors()); |
| 2426 int descriptors = new_map->NumberOfOwnDescriptors(); | 2401 int old_nof = old_map->NumberOfOwnDescriptors(); |
| 2402 int new_nof = new_map->NumberOfOwnDescriptors(); |
| 2427 | 2403 |
| 2428 for (int i = 0; i < descriptors; i++) { | 2404 // This method only supports generalizing instances to at least the same |
| 2405 // number of properties. |
| 2406 ASSERT(old_nof <= new_nof); |
| 2407 |
| 2408 for (int i = 0; i < old_nof; i++) { |
| 2429 PropertyDetails details = new_descriptors->GetDetails(i); | 2409 PropertyDetails details = new_descriptors->GetDetails(i); |
| 2430 if (details.type() != FIELD) continue; | 2410 if (details.type() != FIELD) continue; |
| 2431 PropertyDetails old_details = old_descriptors->GetDetails(i); | 2411 PropertyDetails old_details = old_descriptors->GetDetails(i); |
| 2432 if (old_details.type() == CALLBACKS) { | 2412 if (old_details.type() == CALLBACKS) { |
| 2433 ASSERT(details.representation().IsTagged()); | 2413 ASSERT(details.representation().IsTagged()); |
| 2434 continue; | 2414 continue; |
| 2435 } | 2415 } |
| 2436 ASSERT(old_details.type() == CONSTANT || | 2416 ASSERT(old_details.type() == CONSTANT || |
| 2437 old_details.type() == FIELD); | 2417 old_details.type() == FIELD); |
| 2438 Object* raw_value = old_details.type() == CONSTANT | 2418 Object* raw_value = old_details.type() == CONSTANT |
| 2439 ? old_descriptors->GetValue(i) | 2419 ? old_descriptors->GetValue(i) |
| 2440 : object->RawFastPropertyAt(old_descriptors->GetFieldIndex(i)); | 2420 : object->RawFastPropertyAt(old_descriptors->GetFieldIndex(i)); |
| 2441 Handle<Object> value(raw_value, isolate); | 2421 Handle<Object> value(raw_value, isolate); |
| 2442 if (FLAG_track_double_fields && | 2422 if (!old_details.representation().IsDouble() && |
| 2443 !old_details.representation().IsDouble() && | |
| 2444 details.representation().IsDouble()) { | 2423 details.representation().IsDouble()) { |
| 2445 if (old_details.representation().IsNone()) { | 2424 if (old_details.representation().IsNone()) { |
| 2446 value = handle(Smi::FromInt(0), isolate); | 2425 value = handle(Smi::FromInt(0), isolate); |
| 2447 } | 2426 } |
| 2448 value = NewStorageFor(isolate, value, details.representation()); | 2427 value = NewStorageFor(isolate, value, details.representation()); |
| 2449 } | 2428 } |
| 2450 ASSERT(!(FLAG_track_double_fields && | 2429 ASSERT(!(details.representation().IsDouble() && value->IsSmi())); |
| 2451 details.representation().IsDouble() && | |
| 2452 value->IsSmi())); | |
| 2453 int target_index = new_descriptors->GetFieldIndex(i) - inobject; | 2430 int target_index = new_descriptors->GetFieldIndex(i) - inobject; |
| 2454 if (target_index < 0) target_index += total_size; | 2431 if (target_index < 0) target_index += total_size; |
| 2455 array->set(target_index, *value); | 2432 array->set(target_index, *value); |
| 2456 } | 2433 } |
| 2457 | 2434 |
| 2435 for (int i = old_nof; i < new_nof; i++) { |
| 2436 PropertyDetails details = new_descriptors->GetDetails(i); |
| 2437 if (details.type() != FIELD) continue; |
| 2438 if (details.representation().IsDouble()) { |
| 2439 int target_index = new_descriptors->GetFieldIndex(i) - inobject; |
| 2440 if (target_index < 0) target_index += total_size; |
| 2441 Handle<Object> box = isolate->factory()->NewHeapNumber(0); |
| 2442 array->set(target_index, *box); |
| 2443 } |
| 2444 } |
| 2445 |
| 2458 // From here on we cannot fail and we shouldn't GC anymore. | 2446 // From here on we cannot fail and we shouldn't GC anymore. |
| 2459 DisallowHeapAllocation no_allocation; | 2447 DisallowHeapAllocation no_allocation; |
| 2460 | 2448 |
| 2461 // Copy (real) inobject properties. If necessary, stop at number_of_fields to | 2449 // Copy (real) inobject properties. If necessary, stop at number_of_fields to |
| 2462 // avoid overwriting |one_pointer_filler_map|. | 2450 // avoid overwriting |one_pointer_filler_map|. |
| 2463 int limit = Min(inobject, number_of_fields); | 2451 int limit = Min(inobject, number_of_fields); |
| 2464 for (int i = 0; i < limit; i++) { | 2452 for (int i = 0; i < limit; i++) { |
| 2465 object->FastPropertyAtPut(i, array->get(external + i)); | 2453 object->FastPropertyAtPut(i, array->get(external + i)); |
| 2466 } | 2454 } |
| 2467 | 2455 |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2545 new_map->NumberOfOwnDescriptors(), | 2533 new_map->NumberOfOwnDescriptors(), |
| 2546 new_map->NumberOfOwnDescriptors(), | 2534 new_map->NumberOfOwnDescriptors(), |
| 2547 details.type() == CONSTANT && store_mode == FORCE_FIELD, | 2535 details.type() == CONSTANT && store_mode == FORCE_FIELD, |
| 2548 Representation::Tagged(), Representation::Tagged()); | 2536 Representation::Tagged(), Representation::Tagged()); |
| 2549 } | 2537 } |
| 2550 return new_map; | 2538 return new_map; |
| 2551 } | 2539 } |
| 2552 | 2540 |
| 2553 | 2541 |
| 2554 void Map::DeprecateTransitionTree() { | 2542 void Map::DeprecateTransitionTree() { |
| 2555 if (!FLAG_track_fields) return; | |
| 2556 if (is_deprecated()) return; | 2543 if (is_deprecated()) return; |
| 2557 if (HasTransitionArray()) { | 2544 if (HasTransitionArray()) { |
| 2558 TransitionArray* transitions = this->transitions(); | 2545 TransitionArray* transitions = this->transitions(); |
| 2559 for (int i = 0; i < transitions->number_of_transitions(); i++) { | 2546 for (int i = 0; i < transitions->number_of_transitions(); i++) { |
| 2560 transitions->GetTarget(i)->DeprecateTransitionTree(); | 2547 transitions->GetTarget(i)->DeprecateTransitionTree(); |
| 2561 } | 2548 } |
| 2562 } | 2549 } |
| 2563 deprecate(); | 2550 deprecate(); |
| 2564 dependent_code()->DeoptimizeDependentCodeGroup( | 2551 dependent_code()->DeoptimizeDependentCodeGroup( |
| 2565 GetIsolate(), DependentCode::kTransitionGroup); | 2552 GetIsolate(), DependentCode::kTransitionGroup); |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2626 PropertyDetails details = descriptors->GetDetails(i); | 2613 PropertyDetails details = descriptors->GetDetails(i); |
| 2627 PropertyDetails target_details = | 2614 PropertyDetails target_details = |
| 2628 current->instance_descriptors()->GetDetails(i); | 2615 current->instance_descriptors()->GetDetails(i); |
| 2629 if (details.attributes() != target_details.attributes()) return NULL; | 2616 if (details.attributes() != target_details.attributes()) return NULL; |
| 2630 if (details.type() == CALLBACKS) { | 2617 if (details.type() == CALLBACKS) { |
| 2631 if (target_details.type() != CALLBACKS) return NULL; | 2618 if (target_details.type() != CALLBACKS) return NULL; |
| 2632 if (descriptors->GetValue(i) != | 2619 if (descriptors->GetValue(i) != |
| 2633 current->instance_descriptors()->GetValue(i)) { | 2620 current->instance_descriptors()->GetValue(i)) { |
| 2634 return NULL; | 2621 return NULL; |
| 2635 } | 2622 } |
| 2623 } else if (target_details.type() == CALLBACKS) { |
| 2624 return NULL; |
| 2636 } | 2625 } |
| 2637 } | 2626 } |
| 2638 | 2627 |
| 2639 return current; | 2628 return current; |
| 2640 } | 2629 } |
| 2641 | 2630 |
| 2642 | 2631 |
| 2643 Map* Map::FindLastMatchMap(int verbatim, | 2632 Map* Map::FindLastMatchMap(int verbatim, |
| 2644 int length, | 2633 int length, |
| 2645 DescriptorArray* descriptors) { | 2634 DescriptorArray* descriptors) { |
| (...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2847 | 2836 |
| 2848 return handle(updated); | 2837 return handle(updated); |
| 2849 } | 2838 } |
| 2850 | 2839 |
| 2851 | 2840 |
| 2852 Handle<Object> JSObject::SetPropertyWithInterceptor( | 2841 Handle<Object> JSObject::SetPropertyWithInterceptor( |
| 2853 Handle<JSObject> object, | 2842 Handle<JSObject> object, |
| 2854 Handle<Name> name, | 2843 Handle<Name> name, |
| 2855 Handle<Object> value, | 2844 Handle<Object> value, |
| 2856 PropertyAttributes attributes, | 2845 PropertyAttributes attributes, |
| 2857 StrictModeFlag strict_mode) { | 2846 StrictMode strict_mode) { |
| 2858 // TODO(rossberg): Support symbols in the API. | 2847 // TODO(rossberg): Support symbols in the API. |
| 2859 if (name->IsSymbol()) return value; | 2848 if (name->IsSymbol()) return value; |
| 2860 Isolate* isolate = object->GetIsolate(); | 2849 Isolate* isolate = object->GetIsolate(); |
| 2861 Handle<String> name_string = Handle<String>::cast(name); | 2850 Handle<String> name_string = Handle<String>::cast(name); |
| 2862 Handle<InterceptorInfo> interceptor(object->GetNamedInterceptor()); | 2851 Handle<InterceptorInfo> interceptor(object->GetNamedInterceptor()); |
| 2863 if (!interceptor->setter()->IsUndefined()) { | 2852 if (!interceptor->setter()->IsUndefined()) { |
| 2864 LOG(isolate, | 2853 LOG(isolate, |
| 2865 ApiNamedPropertyAccess("interceptor-named-set", *object, *name)); | 2854 ApiNamedPropertyAccess("interceptor-named-set", *object, *name)); |
| 2866 PropertyCallbackArguments args( | 2855 PropertyCallbackArguments args( |
| 2867 isolate, interceptor->data(), *object, *object); | 2856 isolate, interceptor->data(), *object, *object); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 2879 SetPropertyPostInterceptor(object, name, value, attributes, strict_mode); | 2868 SetPropertyPostInterceptor(object, name, value, attributes, strict_mode); |
| 2880 RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object); | 2869 RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object); |
| 2881 return result; | 2870 return result; |
| 2882 } | 2871 } |
| 2883 | 2872 |
| 2884 | 2873 |
| 2885 Handle<Object> JSReceiver::SetProperty(Handle<JSReceiver> object, | 2874 Handle<Object> JSReceiver::SetProperty(Handle<JSReceiver> object, |
| 2886 Handle<Name> name, | 2875 Handle<Name> name, |
| 2887 Handle<Object> value, | 2876 Handle<Object> value, |
| 2888 PropertyAttributes attributes, | 2877 PropertyAttributes attributes, |
| 2889 StrictModeFlag strict_mode, | 2878 StrictMode strict_mode, |
| 2890 StoreFromKeyed store_mode) { | 2879 StoreFromKeyed store_mode) { |
| 2891 LookupResult result(object->GetIsolate()); | 2880 LookupResult result(object->GetIsolate()); |
| 2892 object->LocalLookup(*name, &result, true); | 2881 object->LocalLookup(*name, &result, true); |
| 2893 if (!result.IsFound()) { | 2882 if (!result.IsFound()) { |
| 2894 object->map()->LookupTransition(JSObject::cast(*object), *name, &result); | 2883 object->map()->LookupTransition(JSObject::cast(*object), *name, &result); |
| 2895 } | 2884 } |
| 2896 return SetProperty(object, &result, name, value, attributes, strict_mode, | 2885 return SetProperty(object, &result, name, value, attributes, strict_mode, |
| 2897 store_mode); | 2886 store_mode); |
| 2898 } | 2887 } |
| 2899 | 2888 |
| 2900 | 2889 |
| 2901 Handle<Object> JSObject::SetPropertyWithCallback(Handle<JSObject> object, | 2890 Handle<Object> JSObject::SetPropertyWithCallback(Handle<JSObject> object, |
| 2902 Handle<Object> structure, | 2891 Handle<Object> structure, |
| 2903 Handle<Name> name, | 2892 Handle<Name> name, |
| 2904 Handle<Object> value, | 2893 Handle<Object> value, |
| 2905 Handle<JSObject> holder, | 2894 Handle<JSObject> holder, |
| 2906 StrictModeFlag strict_mode) { | 2895 StrictMode strict_mode) { |
| 2907 Isolate* isolate = object->GetIsolate(); | 2896 Isolate* isolate = object->GetIsolate(); |
| 2908 | 2897 |
| 2909 // We should never get here to initialize a const with the hole | 2898 // We should never get here to initialize a const with the hole |
| 2910 // value since a const declaration would conflict with the setter. | 2899 // value since a const declaration would conflict with the setter. |
| 2911 ASSERT(!value->IsTheHole()); | 2900 ASSERT(!value->IsTheHole()); |
| 2912 | 2901 |
| 2913 // To accommodate both the old and the new api we switch on the | 2902 // To accommodate both the old and the new api we switch on the |
| 2914 // data structure used to store the callbacks. Eventually foreign | 2903 // data structure used to store the callbacks. Eventually foreign |
| 2915 // callbacks should be phased out. | 2904 // callbacks should be phased out. |
| 2916 if (structure->IsForeign()) { | 2905 if (structure->IsForeign()) { |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2955 return value; | 2944 return value; |
| 2956 } | 2945 } |
| 2957 | 2946 |
| 2958 if (structure->IsAccessorPair()) { | 2947 if (structure->IsAccessorPair()) { |
| 2959 Handle<Object> setter(AccessorPair::cast(*structure)->setter(), isolate); | 2948 Handle<Object> setter(AccessorPair::cast(*structure)->setter(), isolate); |
| 2960 if (setter->IsSpecFunction()) { | 2949 if (setter->IsSpecFunction()) { |
| 2961 // TODO(rossberg): nicer would be to cast to some JSCallable here... | 2950 // TODO(rossberg): nicer would be to cast to some JSCallable here... |
| 2962 return SetPropertyWithDefinedSetter( | 2951 return SetPropertyWithDefinedSetter( |
| 2963 object, Handle<JSReceiver>::cast(setter), value); | 2952 object, Handle<JSReceiver>::cast(setter), value); |
| 2964 } else { | 2953 } else { |
| 2965 if (strict_mode == kNonStrictMode) { | 2954 if (strict_mode == SLOPPY) return value; |
| 2966 return value; | |
| 2967 } | |
| 2968 Handle<Object> args[2] = { name, holder }; | 2955 Handle<Object> args[2] = { name, holder }; |
| 2969 Handle<Object> error = | 2956 Handle<Object> error = |
| 2970 isolate->factory()->NewTypeError("no_setter_in_callback", | 2957 isolate->factory()->NewTypeError("no_setter_in_callback", |
| 2971 HandleVector(args, 2)); | 2958 HandleVector(args, 2)); |
| 2972 isolate->Throw(*error); | 2959 isolate->Throw(*error); |
| 2973 return Handle<Object>(); | 2960 return Handle<Object>(); |
| 2974 } | 2961 } |
| 2975 } | 2962 } |
| 2976 | 2963 |
| 2977 // TODO(dcarney): Handle correctly. | 2964 // TODO(dcarney): Handle correctly. |
| (...skipping 30 matching lines...) Expand all Loading... |
| 3008 if (has_pending_exception) return Handle<Object>(); | 2995 if (has_pending_exception) return Handle<Object>(); |
| 3009 return value; | 2996 return value; |
| 3010 } | 2997 } |
| 3011 | 2998 |
| 3012 | 2999 |
| 3013 Handle<Object> JSObject::SetElementWithCallbackSetterInPrototypes( | 3000 Handle<Object> JSObject::SetElementWithCallbackSetterInPrototypes( |
| 3014 Handle<JSObject> object, | 3001 Handle<JSObject> object, |
| 3015 uint32_t index, | 3002 uint32_t index, |
| 3016 Handle<Object> value, | 3003 Handle<Object> value, |
| 3017 bool* found, | 3004 bool* found, |
| 3018 StrictModeFlag strict_mode) { | 3005 StrictMode strict_mode) { |
| 3019 Isolate *isolate = object->GetIsolate(); | 3006 Isolate *isolate = object->GetIsolate(); |
| 3020 for (Handle<Object> proto = handle(object->GetPrototype(), isolate); | 3007 for (Handle<Object> proto = handle(object->GetPrototype(), isolate); |
| 3021 !proto->IsNull(); | 3008 !proto->IsNull(); |
| 3022 proto = handle(proto->GetPrototype(isolate), isolate)) { | 3009 proto = handle(proto->GetPrototype(isolate), isolate)) { |
| 3023 if (proto->IsJSProxy()) { | 3010 if (proto->IsJSProxy()) { |
| 3024 return JSProxy::SetPropertyViaPrototypesWithHandler( | 3011 return JSProxy::SetPropertyViaPrototypesWithHandler( |
| 3025 Handle<JSProxy>::cast(proto), | 3012 Handle<JSProxy>::cast(proto), |
| 3026 object, | 3013 object, |
| 3027 isolate->factory()->Uint32ToString(index), // name | 3014 isolate->factory()->Uint32ToString(index), // name |
| 3028 value, | 3015 value, |
| (...skipping 19 matching lines...) Expand all Loading... |
| 3048 } | 3035 } |
| 3049 *found = false; | 3036 *found = false; |
| 3050 return isolate->factory()->the_hole_value(); | 3037 return isolate->factory()->the_hole_value(); |
| 3051 } | 3038 } |
| 3052 | 3039 |
| 3053 | 3040 |
| 3054 Handle<Object> JSObject::SetPropertyViaPrototypes(Handle<JSObject> object, | 3041 Handle<Object> JSObject::SetPropertyViaPrototypes(Handle<JSObject> object, |
| 3055 Handle<Name> name, | 3042 Handle<Name> name, |
| 3056 Handle<Object> value, | 3043 Handle<Object> value, |
| 3057 PropertyAttributes attributes, | 3044 PropertyAttributes attributes, |
| 3058 StrictModeFlag strict_mode, | 3045 StrictMode strict_mode, |
| 3059 bool* done) { | 3046 bool* done) { |
| 3060 Isolate* isolate = object->GetIsolate(); | 3047 Isolate* isolate = object->GetIsolate(); |
| 3061 | 3048 |
| 3062 *done = false; | 3049 *done = false; |
| 3063 // We could not find a local property so let's check whether there is an | 3050 // We could not find a local property so let's check whether there is an |
| 3064 // accessor that wants to handle the property, or whether the property is | 3051 // accessor that wants to handle the property, or whether the property is |
| 3065 // read-only on the prototype chain. | 3052 // read-only on the prototype chain. |
| 3066 LookupResult result(isolate); | 3053 LookupResult result(isolate); |
| 3067 object->LookupRealNamedPropertyInPrototypes(*name, &result); | 3054 object->LookupRealNamedPropertyInPrototypes(*name, &result); |
| 3068 if (result.IsFound()) { | 3055 if (result.IsFound()) { |
| 3069 switch (result.type()) { | 3056 switch (result.type()) { |
| 3070 case NORMAL: | 3057 case NORMAL: |
| 3071 case FIELD: | 3058 case FIELD: |
| 3072 case CONSTANT: | 3059 case CONSTANT: |
| 3073 *done = result.IsReadOnly(); | 3060 *done = result.IsReadOnly(); |
| 3074 break; | 3061 break; |
| 3075 case INTERCEPTOR: { | 3062 case INTERCEPTOR: { |
| 3076 PropertyAttributes attr = | 3063 PropertyAttributes attr = GetPropertyAttributeWithInterceptor( |
| 3077 result.holder()->GetPropertyAttributeWithInterceptor( | 3064 handle(result.holder()), object, name, true); |
| 3078 *object, *name, true); | |
| 3079 *done = !!(attr & READ_ONLY); | 3065 *done = !!(attr & READ_ONLY); |
| 3080 break; | 3066 break; |
| 3081 } | 3067 } |
| 3082 case CALLBACKS: { | 3068 case CALLBACKS: { |
| 3083 if (!FLAG_es5_readonly && result.IsReadOnly()) break; | |
| 3084 *done = true; | 3069 *done = true; |
| 3085 Handle<Object> callback_object(result.GetCallbackObject(), isolate); | 3070 Handle<Object> callback_object(result.GetCallbackObject(), isolate); |
| 3086 return SetPropertyWithCallback(object, callback_object, name, value, | 3071 return SetPropertyWithCallback(object, callback_object, name, value, |
| 3087 handle(result.holder()), strict_mode); | 3072 handle(result.holder()), strict_mode); |
| 3088 } | 3073 } |
| 3089 case HANDLER: { | 3074 case HANDLER: { |
| 3090 Handle<JSProxy> proxy(result.proxy()); | 3075 Handle<JSProxy> proxy(result.proxy()); |
| 3091 return JSProxy::SetPropertyViaPrototypesWithHandler( | 3076 return JSProxy::SetPropertyViaPrototypesWithHandler( |
| 3092 proxy, object, name, value, attributes, strict_mode, done); | 3077 proxy, object, name, value, attributes, strict_mode, done); |
| 3093 } | 3078 } |
| 3094 case TRANSITION: | 3079 case TRANSITION: |
| 3095 case NONEXISTENT: | 3080 case NONEXISTENT: |
| 3096 UNREACHABLE(); | 3081 UNREACHABLE(); |
| 3097 break; | 3082 break; |
| 3098 } | 3083 } |
| 3099 } | 3084 } |
| 3100 | 3085 |
| 3101 // If we get here with *done true, we have encountered a read-only property. | 3086 // If we get here with *done true, we have encountered a read-only property. |
| 3102 if (!FLAG_es5_readonly) *done = false; | |
| 3103 if (*done) { | 3087 if (*done) { |
| 3104 if (strict_mode == kNonStrictMode) return value; | 3088 if (strict_mode == SLOPPY) return value; |
| 3105 Handle<Object> args[] = { name, object }; | 3089 Handle<Object> args[] = { name, object }; |
| 3106 Handle<Object> error = isolate->factory()->NewTypeError( | 3090 Handle<Object> error = isolate->factory()->NewTypeError( |
| 3107 "strict_read_only_property", HandleVector(args, ARRAY_SIZE(args))); | 3091 "strict_read_only_property", HandleVector(args, ARRAY_SIZE(args))); |
| 3108 isolate->Throw(*error); | 3092 isolate->Throw(*error); |
| 3109 return Handle<Object>(); | 3093 return Handle<Object>(); |
| 3110 } | 3094 } |
| 3111 return isolate->factory()->the_hole_value(); | 3095 return isolate->factory()->the_hole_value(); |
| 3112 } | 3096 } |
| 3113 | 3097 |
| 3114 | 3098 |
| (...skipping 268 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3383 | 3367 |
| 3384 if (closest_map->elements_kind() == kind) { | 3368 if (closest_map->elements_kind() == kind) { |
| 3385 return closest_map; | 3369 return closest_map; |
| 3386 } | 3370 } |
| 3387 | 3371 |
| 3388 return AddMissingElementsTransitions(closest_map, kind); | 3372 return AddMissingElementsTransitions(closest_map, kind); |
| 3389 } | 3373 } |
| 3390 | 3374 |
| 3391 | 3375 |
| 3392 void JSObject::LocalLookupRealNamedProperty(Name* name, LookupResult* result) { | 3376 void JSObject::LocalLookupRealNamedProperty(Name* name, LookupResult* result) { |
| 3377 DisallowHeapAllocation no_gc; |
| 3393 if (IsJSGlobalProxy()) { | 3378 if (IsJSGlobalProxy()) { |
| 3394 Object* proto = GetPrototype(); | 3379 Object* proto = GetPrototype(); |
| 3395 if (proto->IsNull()) return result->NotFound(); | 3380 if (proto->IsNull()) return result->NotFound(); |
| 3396 ASSERT(proto->IsJSGlobalObject()); | 3381 ASSERT(proto->IsJSGlobalObject()); |
| 3397 return JSObject::cast(proto)->LocalLookupRealNamedProperty(name, result); | 3382 return JSObject::cast(proto)->LocalLookupRealNamedProperty(name, result); |
| 3398 } | 3383 } |
| 3399 | 3384 |
| 3400 if (HasFastProperties()) { | 3385 if (HasFastProperties()) { |
| 3401 map()->LookupDescriptor(this, name, result); | 3386 map()->LookupDescriptor(this, name, result); |
| 3402 // A property or a map transition was found. We return all of these result | 3387 // A property or a map transition was found. We return all of these result |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3462 } | 3447 } |
| 3463 | 3448 |
| 3464 | 3449 |
| 3465 // We only need to deal with CALLBACKS and INTERCEPTORS | 3450 // We only need to deal with CALLBACKS and INTERCEPTORS |
| 3466 Handle<Object> JSObject::SetPropertyWithFailedAccessCheck( | 3451 Handle<Object> JSObject::SetPropertyWithFailedAccessCheck( |
| 3467 Handle<JSObject> object, | 3452 Handle<JSObject> object, |
| 3468 LookupResult* result, | 3453 LookupResult* result, |
| 3469 Handle<Name> name, | 3454 Handle<Name> name, |
| 3470 Handle<Object> value, | 3455 Handle<Object> value, |
| 3471 bool check_prototype, | 3456 bool check_prototype, |
| 3472 StrictModeFlag strict_mode) { | 3457 StrictMode strict_mode) { |
| 3473 if (check_prototype && !result->IsProperty()) { | 3458 if (check_prototype && !result->IsProperty()) { |
| 3474 object->LookupRealNamedPropertyInPrototypes(*name, result); | 3459 object->LookupRealNamedPropertyInPrototypes(*name, result); |
| 3475 } | 3460 } |
| 3476 | 3461 |
| 3477 if (result->IsProperty()) { | 3462 if (result->IsProperty()) { |
| 3478 if (!result->IsReadOnly()) { | 3463 if (!result->IsReadOnly()) { |
| 3479 switch (result->type()) { | 3464 switch (result->type()) { |
| 3480 case CALLBACKS: { | 3465 case CALLBACKS: { |
| 3481 Object* obj = result->GetCallbackObject(); | 3466 Object* obj = result->GetCallbackObject(); |
| 3482 if (obj->IsAccessorInfo()) { | 3467 if (obj->IsAccessorInfo()) { |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3518 break; | 3503 break; |
| 3519 } | 3504 } |
| 3520 default: { | 3505 default: { |
| 3521 break; | 3506 break; |
| 3522 } | 3507 } |
| 3523 } | 3508 } |
| 3524 } | 3509 } |
| 3525 } | 3510 } |
| 3526 | 3511 |
| 3527 Isolate* isolate = object->GetIsolate(); | 3512 Isolate* isolate = object->GetIsolate(); |
| 3528 isolate->ReportFailedAccessCheck(*object, v8::ACCESS_SET); | 3513 isolate->ReportFailedAccessCheckWrapper(object, v8::ACCESS_SET); |
| 3529 RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object); | 3514 RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object); |
| 3530 return value; | 3515 return value; |
| 3531 } | 3516 } |
| 3532 | 3517 |
| 3533 | 3518 |
| 3534 Handle<Object> JSReceiver::SetProperty(Handle<JSReceiver> object, | 3519 Handle<Object> JSReceiver::SetProperty(Handle<JSReceiver> object, |
| 3535 LookupResult* result, | 3520 LookupResult* result, |
| 3536 Handle<Name> key, | 3521 Handle<Name> key, |
| 3537 Handle<Object> value, | 3522 Handle<Object> value, |
| 3538 PropertyAttributes attributes, | 3523 PropertyAttributes attributes, |
| 3539 StrictModeFlag strict_mode, | 3524 StrictMode strict_mode, |
| 3540 StoreFromKeyed store_mode) { | 3525 StoreFromKeyed store_mode) { |
| 3541 if (result->IsHandler()) { | 3526 if (result->IsHandler()) { |
| 3542 return JSProxy::SetPropertyWithHandler(handle(result->proxy()), | 3527 return JSProxy::SetPropertyWithHandler(handle(result->proxy()), |
| 3543 object, key, value, attributes, strict_mode); | 3528 object, key, value, attributes, strict_mode); |
| 3544 } else { | 3529 } else { |
| 3545 return JSObject::SetPropertyForResult(Handle<JSObject>::cast(object), | 3530 return JSObject::SetPropertyForResult(Handle<JSObject>::cast(object), |
| 3546 result, key, value, attributes, strict_mode, store_mode); | 3531 result, key, value, attributes, strict_mode, store_mode); |
| 3547 } | 3532 } |
| 3548 } | 3533 } |
| 3549 | 3534 |
| (...skipping 11 matching lines...) Expand all Loading... |
| 3561 | 3546 |
| 3562 return result->BooleanValue(); | 3547 return result->BooleanValue(); |
| 3563 } | 3548 } |
| 3564 | 3549 |
| 3565 | 3550 |
| 3566 Handle<Object> JSProxy::SetPropertyWithHandler(Handle<JSProxy> proxy, | 3551 Handle<Object> JSProxy::SetPropertyWithHandler(Handle<JSProxy> proxy, |
| 3567 Handle<JSReceiver> receiver, | 3552 Handle<JSReceiver> receiver, |
| 3568 Handle<Name> name, | 3553 Handle<Name> name, |
| 3569 Handle<Object> value, | 3554 Handle<Object> value, |
| 3570 PropertyAttributes attributes, | 3555 PropertyAttributes attributes, |
| 3571 StrictModeFlag strict_mode) { | 3556 StrictMode strict_mode) { |
| 3572 Isolate* isolate = proxy->GetIsolate(); | 3557 Isolate* isolate = proxy->GetIsolate(); |
| 3573 | 3558 |
| 3574 // TODO(rossberg): adjust once there is a story for symbols vs proxies. | 3559 // TODO(rossberg): adjust once there is a story for symbols vs proxies. |
| 3575 if (name->IsSymbol()) return value; | 3560 if (name->IsSymbol()) return value; |
| 3576 | 3561 |
| 3577 Handle<Object> args[] = { receiver, name, value }; | 3562 Handle<Object> args[] = { receiver, name, value }; |
| 3578 proxy->CallTrap("set", isolate->derived_set_trap(), ARRAY_SIZE(args), args); | 3563 proxy->CallTrap("set", isolate->derived_set_trap(), ARRAY_SIZE(args), args); |
| 3579 if (isolate->has_pending_exception()) return Handle<Object>(); | 3564 if (isolate->has_pending_exception()) return Handle<Object>(); |
| 3580 | 3565 |
| 3581 return value; | 3566 return value; |
| 3582 } | 3567 } |
| 3583 | 3568 |
| 3584 | 3569 |
| 3585 Handle<Object> JSProxy::SetPropertyViaPrototypesWithHandler( | 3570 Handle<Object> JSProxy::SetPropertyViaPrototypesWithHandler( |
| 3586 Handle<JSProxy> proxy, | 3571 Handle<JSProxy> proxy, |
| 3587 Handle<JSReceiver> receiver, | 3572 Handle<JSReceiver> receiver, |
| 3588 Handle<Name> name, | 3573 Handle<Name> name, |
| 3589 Handle<Object> value, | 3574 Handle<Object> value, |
| 3590 PropertyAttributes attributes, | 3575 PropertyAttributes attributes, |
| 3591 StrictModeFlag strict_mode, | 3576 StrictMode strict_mode, |
| 3592 bool* done) { | 3577 bool* done) { |
| 3593 Isolate* isolate = proxy->GetIsolate(); | 3578 Isolate* isolate = proxy->GetIsolate(); |
| 3594 Handle<Object> handler(proxy->handler(), isolate); // Trap might morph proxy. | 3579 Handle<Object> handler(proxy->handler(), isolate); // Trap might morph proxy. |
| 3595 | 3580 |
| 3596 // TODO(rossberg): adjust once there is a story for symbols vs proxies. | 3581 // TODO(rossberg): adjust once there is a story for symbols vs proxies. |
| 3597 if (name->IsSymbol()) { | 3582 if (name->IsSymbol()) { |
| 3598 *done = false; | 3583 *done = false; |
| 3599 return isolate->factory()->the_hole_value(); | 3584 return isolate->factory()->the_hole_value(); |
| 3600 } | 3585 } |
| 3601 | 3586 |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3649 if (hasWritable->IsTrue()) { | 3634 if (hasWritable->IsTrue()) { |
| 3650 Handle<String> writable_name = | 3635 Handle<String> writable_name = |
| 3651 isolate->factory()->InternalizeOneByteString( | 3636 isolate->factory()->InternalizeOneByteString( |
| 3652 STATIC_ASCII_VECTOR("writable_")); | 3637 STATIC_ASCII_VECTOR("writable_")); |
| 3653 Handle<Object> writable( | 3638 Handle<Object> writable( |
| 3654 v8::internal::GetProperty(isolate, desc, writable_name)); | 3639 v8::internal::GetProperty(isolate, desc, writable_name)); |
| 3655 ASSERT(!isolate->has_pending_exception()); | 3640 ASSERT(!isolate->has_pending_exception()); |
| 3656 ASSERT(writable->IsTrue() || writable->IsFalse()); | 3641 ASSERT(writable->IsTrue() || writable->IsFalse()); |
| 3657 *done = writable->IsFalse(); | 3642 *done = writable->IsFalse(); |
| 3658 if (!*done) return isolate->factory()->the_hole_value(); | 3643 if (!*done) return isolate->factory()->the_hole_value(); |
| 3659 if (strict_mode == kNonStrictMode) return value; | 3644 if (strict_mode == SLOPPY) return value; |
| 3660 Handle<Object> args[] = { name, receiver }; | 3645 Handle<Object> args[] = { name, receiver }; |
| 3661 Handle<Object> error = isolate->factory()->NewTypeError( | 3646 Handle<Object> error = isolate->factory()->NewTypeError( |
| 3662 "strict_read_only_property", HandleVector(args, ARRAY_SIZE(args))); | 3647 "strict_read_only_property", HandleVector(args, ARRAY_SIZE(args))); |
| 3663 isolate->Throw(*error); | 3648 isolate->Throw(*error); |
| 3664 return Handle<Object>(); | 3649 return Handle<Object>(); |
| 3665 } | 3650 } |
| 3666 | 3651 |
| 3667 // We have an AccessorDescriptor. | 3652 // We have an AccessorDescriptor. |
| 3668 Handle<String> set_name = isolate->factory()->InternalizeOneByteString( | 3653 Handle<String> set_name = isolate->factory()->InternalizeOneByteString( |
| 3669 STATIC_ASCII_VECTOR("set_")); | 3654 STATIC_ASCII_VECTOR("set_")); |
| 3670 Handle<Object> setter(v8::internal::GetProperty(isolate, desc, set_name)); | 3655 Handle<Object> setter(v8::internal::GetProperty(isolate, desc, set_name)); |
| 3671 ASSERT(!isolate->has_pending_exception()); | 3656 ASSERT(!isolate->has_pending_exception()); |
| 3672 if (!setter->IsUndefined()) { | 3657 if (!setter->IsUndefined()) { |
| 3673 // TODO(rossberg): nicer would be to cast to some JSCallable here... | 3658 // TODO(rossberg): nicer would be to cast to some JSCallable here... |
| 3674 return SetPropertyWithDefinedSetter( | 3659 return SetPropertyWithDefinedSetter( |
| 3675 receiver, Handle<JSReceiver>::cast(setter), value); | 3660 receiver, Handle<JSReceiver>::cast(setter), value); |
| 3676 } | 3661 } |
| 3677 | 3662 |
| 3678 if (strict_mode == kNonStrictMode) return value; | 3663 if (strict_mode == SLOPPY) return value; |
| 3679 Handle<Object> args2[] = { name, proxy }; | 3664 Handle<Object> args2[] = { name, proxy }; |
| 3680 Handle<Object> error = isolate->factory()->NewTypeError( | 3665 Handle<Object> error = isolate->factory()->NewTypeError( |
| 3681 "no_setter_in_callback", HandleVector(args2, ARRAY_SIZE(args2))); | 3666 "no_setter_in_callback", HandleVector(args2, ARRAY_SIZE(args2))); |
| 3682 isolate->Throw(*error); | 3667 isolate->Throw(*error); |
| 3683 return Handle<Object>(); | 3668 return Handle<Object>(); |
| 3684 } | 3669 } |
| 3685 | 3670 |
| 3686 | 3671 |
| 3687 Handle<Object> JSProxy::DeletePropertyWithHandler( | 3672 Handle<Object> JSProxy::DeletePropertyWithHandler( |
| 3688 Handle<JSProxy> proxy, Handle<Name> name, DeleteMode mode) { | 3673 Handle<JSProxy> proxy, Handle<Name> name, DeleteMode mode) { |
| (...skipping 23 matching lines...) Expand all Loading... |
| 3712 | 3697 |
| 3713 | 3698 |
| 3714 Handle<Object> JSProxy::DeleteElementWithHandler( | 3699 Handle<Object> JSProxy::DeleteElementWithHandler( |
| 3715 Handle<JSProxy> proxy, uint32_t index, DeleteMode mode) { | 3700 Handle<JSProxy> proxy, uint32_t index, DeleteMode mode) { |
| 3716 Isolate* isolate = proxy->GetIsolate(); | 3701 Isolate* isolate = proxy->GetIsolate(); |
| 3717 Handle<String> name = isolate->factory()->Uint32ToString(index); | 3702 Handle<String> name = isolate->factory()->Uint32ToString(index); |
| 3718 return JSProxy::DeletePropertyWithHandler(proxy, name, mode); | 3703 return JSProxy::DeletePropertyWithHandler(proxy, name, mode); |
| 3719 } | 3704 } |
| 3720 | 3705 |
| 3721 | 3706 |
| 3722 MUST_USE_RESULT PropertyAttributes JSProxy::GetPropertyAttributeWithHandler( | 3707 PropertyAttributes JSProxy::GetPropertyAttributeWithHandler( |
| 3723 JSReceiver* receiver_raw, | 3708 Handle<JSProxy> proxy, |
| 3724 Name* name_raw) { | 3709 Handle<JSReceiver> receiver, |
| 3725 Isolate* isolate = GetIsolate(); | 3710 Handle<Name> name) { |
| 3711 Isolate* isolate = proxy->GetIsolate(); |
| 3726 HandleScope scope(isolate); | 3712 HandleScope scope(isolate); |
| 3727 Handle<JSProxy> proxy(this); | |
| 3728 Handle<Object> handler(this->handler(), isolate); // Trap might morph proxy. | |
| 3729 Handle<JSReceiver> receiver(receiver_raw); | |
| 3730 Handle<Object> name(name_raw, isolate); | |
| 3731 | 3713 |
| 3732 // TODO(rossberg): adjust once there is a story for symbols vs proxies. | 3714 // TODO(rossberg): adjust once there is a story for symbols vs proxies. |
| 3733 if (name->IsSymbol()) return ABSENT; | 3715 if (name->IsSymbol()) return ABSENT; |
| 3734 | 3716 |
| 3735 Handle<Object> args[] = { name }; | 3717 Handle<Object> args[] = { name }; |
| 3736 Handle<Object> result = CallTrap( | 3718 Handle<Object> result = proxy->CallTrap( |
| 3737 "getPropertyDescriptor", Handle<Object>(), ARRAY_SIZE(args), args); | 3719 "getPropertyDescriptor", Handle<Object>(), ARRAY_SIZE(args), args); |
| 3738 if (isolate->has_pending_exception()) return NONE; | 3720 if (isolate->has_pending_exception()) return NONE; |
| 3739 | 3721 |
| 3740 if (result->IsUndefined()) return ABSENT; | 3722 if (result->IsUndefined()) return ABSENT; |
| 3741 | 3723 |
| 3742 bool has_pending_exception; | 3724 bool has_pending_exception; |
| 3743 Handle<Object> argv[] = { result }; | 3725 Handle<Object> argv[] = { result }; |
| 3744 Handle<Object> desc = Execution::Call( | 3726 Handle<Object> desc = Execution::Call( |
| 3745 isolate, isolate->to_complete_property_descriptor(), result, | 3727 isolate, isolate->to_complete_property_descriptor(), result, |
| 3746 ARRAY_SIZE(argv), argv, &has_pending_exception); | 3728 ARRAY_SIZE(argv), argv, &has_pending_exception); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 3761 if (isolate->has_pending_exception()) return NONE; | 3743 if (isolate->has_pending_exception()) return NONE; |
| 3762 if (!writable->BooleanValue()) { | 3744 if (!writable->BooleanValue()) { |
| 3763 Handle<String> set_n = isolate->factory()->InternalizeOneByteString( | 3745 Handle<String> set_n = isolate->factory()->InternalizeOneByteString( |
| 3764 STATIC_ASCII_VECTOR("set_")); | 3746 STATIC_ASCII_VECTOR("set_")); |
| 3765 Handle<Object> setter(v8::internal::GetProperty(isolate, desc, set_n)); | 3747 Handle<Object> setter(v8::internal::GetProperty(isolate, desc, set_n)); |
| 3766 if (isolate->has_pending_exception()) return NONE; | 3748 if (isolate->has_pending_exception()) return NONE; |
| 3767 writable = isolate->factory()->ToBoolean(!setter->IsUndefined()); | 3749 writable = isolate->factory()->ToBoolean(!setter->IsUndefined()); |
| 3768 } | 3750 } |
| 3769 | 3751 |
| 3770 if (configurable->IsFalse()) { | 3752 if (configurable->IsFalse()) { |
| 3753 Handle<Object> handler(proxy->handler(), isolate); |
| 3771 Handle<String> trap = isolate->factory()->InternalizeOneByteString( | 3754 Handle<String> trap = isolate->factory()->InternalizeOneByteString( |
| 3772 STATIC_ASCII_VECTOR("getPropertyDescriptor")); | 3755 STATIC_ASCII_VECTOR("getPropertyDescriptor")); |
| 3773 Handle<Object> args[] = { handler, trap, name }; | 3756 Handle<Object> args[] = { handler, trap, name }; |
| 3774 Handle<Object> error = isolate->factory()->NewTypeError( | 3757 Handle<Object> error = isolate->factory()->NewTypeError( |
| 3775 "proxy_prop_not_configurable", HandleVector(args, ARRAY_SIZE(args))); | 3758 "proxy_prop_not_configurable", HandleVector(args, ARRAY_SIZE(args))); |
| 3776 isolate->Throw(*error); | 3759 isolate->Throw(*error); |
| 3777 return NONE; | 3760 return NONE; |
| 3778 } | 3761 } |
| 3779 | 3762 |
| 3780 int attributes = NONE; | 3763 int attributes = NONE; |
| 3781 if (!enumerable->BooleanValue()) attributes |= DONT_ENUM; | 3764 if (!enumerable->BooleanValue()) attributes |= DONT_ENUM; |
| 3782 if (!configurable->BooleanValue()) attributes |= DONT_DELETE; | 3765 if (!configurable->BooleanValue()) attributes |= DONT_DELETE; |
| 3783 if (!writable->BooleanValue()) attributes |= READ_ONLY; | 3766 if (!writable->BooleanValue()) attributes |= READ_ONLY; |
| 3784 return static_cast<PropertyAttributes>(attributes); | 3767 return static_cast<PropertyAttributes>(attributes); |
| 3785 } | 3768 } |
| 3786 | 3769 |
| 3787 | 3770 |
| 3788 MUST_USE_RESULT PropertyAttributes JSProxy::GetElementAttributeWithHandler( | 3771 PropertyAttributes JSProxy::GetElementAttributeWithHandler( |
| 3789 JSReceiver* receiver_raw, | 3772 Handle<JSProxy> proxy, |
| 3773 Handle<JSReceiver> receiver, |
| 3790 uint32_t index) { | 3774 uint32_t index) { |
| 3791 Isolate* isolate = GetIsolate(); | 3775 Isolate* isolate = proxy->GetIsolate(); |
| 3792 HandleScope scope(isolate); | |
| 3793 Handle<JSProxy> proxy(this); | |
| 3794 Handle<JSReceiver> receiver(receiver_raw); | |
| 3795 Handle<String> name = isolate->factory()->Uint32ToString(index); | 3776 Handle<String> name = isolate->factory()->Uint32ToString(index); |
| 3796 return proxy->GetPropertyAttributeWithHandler(*receiver, *name); | 3777 return GetPropertyAttributeWithHandler(proxy, receiver, name); |
| 3797 } | 3778 } |
| 3798 | 3779 |
| 3799 | 3780 |
| 3800 void JSProxy::Fix(Handle<JSProxy> proxy) { | 3781 void JSProxy::Fix(Handle<JSProxy> proxy) { |
| 3801 Isolate* isolate = proxy->GetIsolate(); | 3782 Isolate* isolate = proxy->GetIsolate(); |
| 3802 | 3783 |
| 3803 // Save identity hash. | 3784 // Save identity hash. |
| 3804 Handle<Object> hash(proxy->GetIdentityHash(), isolate); | 3785 Handle<Object> hash(proxy->GetIdentityHash(), isolate); |
| 3805 | 3786 |
| 3806 if (proxy->IsJSFunctionProxy()) { | 3787 if (proxy->IsJSFunctionProxy()) { |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3862 IsDictionaryElementsKind(obj_kind)) { | 3843 IsDictionaryElementsKind(obj_kind)) { |
| 3863 to_kind = obj_kind; | 3844 to_kind = obj_kind; |
| 3864 } | 3845 } |
| 3865 if (IsDictionaryElementsKind(to_kind)) { | 3846 if (IsDictionaryElementsKind(to_kind)) { |
| 3866 NormalizeElements(object); | 3847 NormalizeElements(object); |
| 3867 } else { | 3848 } else { |
| 3868 TransitionElementsKind(object, to_kind); | 3849 TransitionElementsKind(object, to_kind); |
| 3869 } | 3850 } |
| 3870 map = MapAsElementsKind(map, to_kind); | 3851 map = MapAsElementsKind(map, to_kind); |
| 3871 } | 3852 } |
| 3872 int total_size = | 3853 JSObject::MigrateToMap(object, map); |
| 3873 map->NumberOfOwnDescriptors() + map->unused_property_fields(); | |
| 3874 int out_of_object = total_size - map->inobject_properties(); | |
| 3875 if (out_of_object != object->properties()->length()) { | |
| 3876 Isolate* isolate = object->GetIsolate(); | |
| 3877 Handle<FixedArray> new_properties = isolate->factory()->CopySizeFixedArray( | |
| 3878 handle(object->properties()), out_of_object); | |
| 3879 object->set_properties(*new_properties); | |
| 3880 } | |
| 3881 object->set_map(*map); | |
| 3882 } | 3854 } |
| 3883 | 3855 |
| 3884 | 3856 |
| 3885 void JSObject::MigrateInstance(Handle<JSObject> object) { | 3857 void JSObject::MigrateInstance(Handle<JSObject> object) { |
| 3886 // Converting any field to the most specific type will cause the | 3858 // Converting any field to the most specific type will cause the |
| 3887 // GeneralizeFieldRepresentation algorithm to create the most general existing | 3859 // GeneralizeFieldRepresentation algorithm to create the most general existing |
| 3888 // transition that matches the object. This achieves what is needed. | 3860 // transition that matches the object. This achieves what is needed. |
| 3889 Handle<Map> original_map(object->map()); | 3861 Handle<Map> original_map(object->map()); |
| 3890 GeneralizeFieldRepresentation( | 3862 GeneralizeFieldRepresentation( |
| 3891 object, 0, Representation::None(), ALLOW_AS_CONSTANT); | 3863 object, 0, Representation::None(), ALLOW_AS_CONSTANT); |
| (...skipping 26 matching lines...) Expand all Loading... |
| 3918 int descriptor = transition_map->LastAdded(); | 3890 int descriptor = transition_map->LastAdded(); |
| 3919 | 3891 |
| 3920 DescriptorArray* descriptors = transition_map->instance_descriptors(); | 3892 DescriptorArray* descriptors = transition_map->instance_descriptors(); |
| 3921 PropertyDetails details = descriptors->GetDetails(descriptor); | 3893 PropertyDetails details = descriptors->GetDetails(descriptor); |
| 3922 | 3894 |
| 3923 if (details.type() == CALLBACKS || attributes != details.attributes()) { | 3895 if (details.type() == CALLBACKS || attributes != details.attributes()) { |
| 3924 // AddProperty will either normalize the object, or create a new fast copy | 3896 // AddProperty will either normalize the object, or create a new fast copy |
| 3925 // of the map. If we get a fast copy of the map, all field representations | 3897 // of the map. If we get a fast copy of the map, all field representations |
| 3926 // will be tagged since the transition is omitted. | 3898 // will be tagged since the transition is omitted. |
| 3927 return JSObject::AddProperty( | 3899 return JSObject::AddProperty( |
| 3928 object, name, value, attributes, kNonStrictMode, | 3900 object, name, value, attributes, SLOPPY, |
| 3929 JSReceiver::CERTAINLY_NOT_STORE_FROM_KEYED, | 3901 JSReceiver::CERTAINLY_NOT_STORE_FROM_KEYED, |
| 3930 JSReceiver::OMIT_EXTENSIBILITY_CHECK, | 3902 JSReceiver::OMIT_EXTENSIBILITY_CHECK, |
| 3931 JSObject::FORCE_TAGGED, FORCE_FIELD, OMIT_TRANSITION); | 3903 JSObject::FORCE_TAGGED, FORCE_FIELD, OMIT_TRANSITION); |
| 3932 } | 3904 } |
| 3933 | 3905 |
| 3934 // Keep the target CONSTANT if the same value is stored. | 3906 // Keep the target CONSTANT if the same value is stored. |
| 3935 // TODO(verwaest): Also support keeping the placeholder | 3907 // TODO(verwaest): Also support keeping the placeholder |
| 3936 // (value->IsUninitialized) as constant. | 3908 // (value->IsUninitialized) as constant. |
| 3937 if (details.type() == CONSTANT && | 3909 if (!value->FitsRepresentation(details.representation()) || |
| 3938 descriptors->GetValue(descriptor) == *value) { | 3910 (details.type() == CONSTANT && |
| 3939 object->set_map(*transition_map); | 3911 descriptors->GetValue(descriptor) != *value)) { |
| 3940 return value; | 3912 transition_map = Map::GeneralizeRepresentation(transition_map, |
| 3913 descriptor, value->OptimalRepresentation(), FORCE_FIELD); |
| 3941 } | 3914 } |
| 3942 | 3915 |
| 3943 Representation representation = details.representation(); | 3916 JSObject::MigrateToMap(object, transition_map); |
| 3944 | 3917 |
| 3945 if (!value->FitsRepresentation(representation) || | 3918 // Reload. |
| 3946 details.type() == CONSTANT) { | 3919 descriptors = transition_map->instance_descriptors(); |
| 3947 transition_map = Map::GeneralizeRepresentation(transition_map, | 3920 details = descriptors->GetDetails(descriptor); |
| 3948 descriptor, value->OptimalRepresentation(), FORCE_FIELD); | 3921 |
| 3949 Object* back = transition_map->GetBackPointer(); | 3922 if (details.type() != FIELD) return value; |
| 3950 if (back->IsMap()) { | 3923 |
| 3951 MigrateToMap(object, handle(Map::cast(back))); | 3924 int field_index = descriptors->GetFieldIndex(descriptor); |
| 3952 } | 3925 if (details.representation().IsDouble()) { |
| 3953 descriptors = transition_map->instance_descriptors(); | 3926 // Nothing more to be done. |
| 3954 representation = descriptors->GetDetails(descriptor).representation(); | 3927 if (value->IsUninitialized()) return value; |
| 3928 HeapNumber* box = HeapNumber::cast(object->RawFastPropertyAt(field_index)); |
| 3929 box->set_value(value->Number()); |
| 3930 } else { |
| 3931 object->FastPropertyAtPut(field_index, *value); |
| 3955 } | 3932 } |
| 3956 | 3933 |
| 3957 int field_index = descriptors->GetFieldIndex(descriptor); | |
| 3958 AddFastPropertyUsingMap( | |
| 3959 object, transition_map, name, value, field_index, representation); | |
| 3960 return value; | 3934 return value; |
| 3961 } | 3935 } |
| 3962 | 3936 |
| 3963 | 3937 |
| 3964 static void SetPropertyToField(LookupResult* lookup, | 3938 static void SetPropertyToField(LookupResult* lookup, |
| 3965 Handle<Name> name, | 3939 Handle<Name> name, |
| 3966 Handle<Object> value) { | 3940 Handle<Object> value) { |
| 3967 Representation representation = lookup->representation(); | 3941 Representation representation = lookup->representation(); |
| 3968 if (!value->FitsRepresentation(representation) || | 3942 if (!value->FitsRepresentation(representation) || |
| 3969 lookup->type() == CONSTANT) { | 3943 lookup->type() == CONSTANT) { |
| 3970 JSObject::GeneralizeFieldRepresentation(handle(lookup->holder()), | 3944 JSObject::GeneralizeFieldRepresentation(handle(lookup->holder()), |
| 3971 lookup->GetDescriptorIndex(), | 3945 lookup->GetDescriptorIndex(), |
| 3972 value->OptimalRepresentation(), | 3946 value->OptimalRepresentation(), |
| 3973 FORCE_FIELD); | 3947 FORCE_FIELD); |
| 3974 DescriptorArray* desc = lookup->holder()->map()->instance_descriptors(); | 3948 DescriptorArray* desc = lookup->holder()->map()->instance_descriptors(); |
| 3975 int descriptor = lookup->GetDescriptorIndex(); | 3949 int descriptor = lookup->GetDescriptorIndex(); |
| 3976 representation = desc->GetDetails(descriptor).representation(); | 3950 representation = desc->GetDetails(descriptor).representation(); |
| 3977 } | 3951 } |
| 3978 | 3952 |
| 3979 if (FLAG_track_double_fields && representation.IsDouble()) { | 3953 if (representation.IsDouble()) { |
| 3980 HeapNumber* storage = HeapNumber::cast(lookup->holder()->RawFastPropertyAt( | 3954 HeapNumber* storage = HeapNumber::cast(lookup->holder()->RawFastPropertyAt( |
| 3981 lookup->GetFieldIndex().field_index())); | 3955 lookup->GetFieldIndex().field_index())); |
| 3982 storage->set_value(value->Number()); | 3956 storage->set_value(value->Number()); |
| 3983 return; | 3957 return; |
| 3984 } | 3958 } |
| 3985 | 3959 |
| 3986 lookup->holder()->FastPropertyAtPut( | 3960 lookup->holder()->FastPropertyAtPut( |
| 3987 lookup->GetFieldIndex().field_index(), *value); | 3961 lookup->GetFieldIndex().field_index(), *value); |
| 3988 } | 3962 } |
| 3989 | 3963 |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4030 ConvertAndSetLocalProperty(lookup, name, value, attributes); | 4004 ConvertAndSetLocalProperty(lookup, name, value, attributes); |
| 4031 } | 4005 } |
| 4032 } | 4006 } |
| 4033 | 4007 |
| 4034 | 4008 |
| 4035 Handle<Object> JSObject::SetPropertyForResult(Handle<JSObject> object, | 4009 Handle<Object> JSObject::SetPropertyForResult(Handle<JSObject> object, |
| 4036 LookupResult* lookup, | 4010 LookupResult* lookup, |
| 4037 Handle<Name> name, | 4011 Handle<Name> name, |
| 4038 Handle<Object> value, | 4012 Handle<Object> value, |
| 4039 PropertyAttributes attributes, | 4013 PropertyAttributes attributes, |
| 4040 StrictModeFlag strict_mode, | 4014 StrictMode strict_mode, |
| 4041 StoreFromKeyed store_mode) { | 4015 StoreFromKeyed store_mode) { |
| 4042 Isolate* isolate = object->GetIsolate(); | 4016 Isolate* isolate = object->GetIsolate(); |
| 4043 | 4017 |
| 4044 // Make sure that the top context does not change when doing callbacks or | 4018 // Make sure that the top context does not change when doing callbacks or |
| 4045 // interceptor calls. | 4019 // interceptor calls. |
| 4046 AssertNoContextChange ncc(isolate); | 4020 AssertNoContextChange ncc(isolate); |
| 4047 | 4021 |
| 4048 // Optimization for 2-byte strings often used as keys in a decompression | 4022 // Optimization for 2-byte strings often used as keys in a decompression |
| 4049 // dictionary. We internalize these short keys to avoid constantly | 4023 // dictionary. We internalize these short keys to avoid constantly |
| 4050 // reallocating them. | 4024 // reallocating them. |
| 4051 if (name->IsString() && !name->IsInternalizedString() && | 4025 if (name->IsString() && !name->IsInternalizedString() && |
| 4052 Handle<String>::cast(name)->length() <= 2) { | 4026 Handle<String>::cast(name)->length() <= 2) { |
| 4053 name = isolate->factory()->InternalizeString(Handle<String>::cast(name)); | 4027 name = isolate->factory()->InternalizeString(Handle<String>::cast(name)); |
| 4054 } | 4028 } |
| 4055 | 4029 |
| 4056 // Check access rights if needed. | 4030 // Check access rights if needed. |
| 4057 if (object->IsAccessCheckNeeded()) { | 4031 if (object->IsAccessCheckNeeded()) { |
| 4058 if (!isolate->MayNamedAccess(*object, *name, v8::ACCESS_SET)) { | 4032 if (!isolate->MayNamedAccessWrapper(object, name, v8::ACCESS_SET)) { |
| 4059 return SetPropertyWithFailedAccessCheck(object, lookup, name, value, | 4033 return SetPropertyWithFailedAccessCheck(object, lookup, name, value, |
| 4060 true, strict_mode); | 4034 true, strict_mode); |
| 4061 } | 4035 } |
| 4062 } | 4036 } |
| 4063 | 4037 |
| 4064 if (object->IsJSGlobalProxy()) { | 4038 if (object->IsJSGlobalProxy()) { |
| 4065 Handle<Object> proto(object->GetPrototype(), isolate); | 4039 Handle<Object> proto(object->GetPrototype(), isolate); |
| 4066 if (proto->IsNull()) return value; | 4040 if (proto->IsNull()) return value; |
| 4067 ASSERT(proto->IsJSGlobalObject()); | 4041 ASSERT(proto->IsJSGlobalObject()); |
| 4068 return SetPropertyForResult(Handle<JSObject>::cast(proto), | 4042 return SetPropertyForResult(Handle<JSObject>::cast(proto), |
| (...skipping 10 matching lines...) Expand all Loading... |
| 4079 if (done) return result_object; | 4053 if (done) return result_object; |
| 4080 } | 4054 } |
| 4081 | 4055 |
| 4082 if (!lookup->IsFound()) { | 4056 if (!lookup->IsFound()) { |
| 4083 // Neither properties nor transitions found. | 4057 // Neither properties nor transitions found. |
| 4084 return AddProperty( | 4058 return AddProperty( |
| 4085 object, name, value, attributes, strict_mode, store_mode); | 4059 object, name, value, attributes, strict_mode, store_mode); |
| 4086 } | 4060 } |
| 4087 | 4061 |
| 4088 if (lookup->IsProperty() && lookup->IsReadOnly()) { | 4062 if (lookup->IsProperty() && lookup->IsReadOnly()) { |
| 4089 if (strict_mode == kStrictMode) { | 4063 if (strict_mode == STRICT) { |
| 4090 Handle<Object> args[] = { name, object }; | 4064 Handle<Object> args[] = { name, object }; |
| 4091 Handle<Object> error = isolate->factory()->NewTypeError( | 4065 Handle<Object> error = isolate->factory()->NewTypeError( |
| 4092 "strict_read_only_property", HandleVector(args, ARRAY_SIZE(args))); | 4066 "strict_read_only_property", HandleVector(args, ARRAY_SIZE(args))); |
| 4093 isolate->Throw(*error); | 4067 isolate->Throw(*error); |
| 4094 return Handle<Object>(); | 4068 return Handle<Object>(); |
| 4095 } else { | 4069 } else { |
| 4096 return value; | 4070 return value; |
| 4097 } | 4071 } |
| 4098 } | 4072 } |
| 4099 | 4073 |
| 4100 Handle<Object> old_value = isolate->factory()->the_hole_value(); | 4074 Handle<Object> old_value = isolate->factory()->the_hole_value(); |
| 4101 bool is_observed = FLAG_harmony_observation && | 4075 bool is_observed = object->map()->is_observed() && |
| 4102 object->map()->is_observed() && | |
| 4103 *name != isolate->heap()->hidden_string(); | 4076 *name != isolate->heap()->hidden_string(); |
| 4104 if (is_observed && lookup->IsDataProperty()) { | 4077 if (is_observed && lookup->IsDataProperty()) { |
| 4105 old_value = Object::GetProperty(object, name); | 4078 old_value = Object::GetProperty(object, name); |
| 4106 } | 4079 } |
| 4107 | 4080 |
| 4108 // This is a real property that is not read-only, or it is a | 4081 // This is a real property that is not read-only, or it is a |
| 4109 // transition or null descriptor and there are no setters in the prototypes. | 4082 // transition or null descriptor and there are no setters in the prototypes. |
| 4110 Handle<Object> result = value; | 4083 Handle<Object> result = value; |
| 4111 switch (lookup->type()) { | 4084 switch (lookup->type()) { |
| 4112 case NORMAL: | 4085 case NORMAL: |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4183 AssertNoContextChange ncc(isolate); | 4156 AssertNoContextChange ncc(isolate); |
| 4184 | 4157 |
| 4185 LookupResult lookup(isolate); | 4158 LookupResult lookup(isolate); |
| 4186 object->LocalLookup(*name, &lookup, true); | 4159 object->LocalLookup(*name, &lookup, true); |
| 4187 if (!lookup.IsFound()) { | 4160 if (!lookup.IsFound()) { |
| 4188 object->map()->LookupTransition(*object, *name, &lookup); | 4161 object->map()->LookupTransition(*object, *name, &lookup); |
| 4189 } | 4162 } |
| 4190 | 4163 |
| 4191 // Check access rights if needed. | 4164 // Check access rights if needed. |
| 4192 if (object->IsAccessCheckNeeded()) { | 4165 if (object->IsAccessCheckNeeded()) { |
| 4193 if (!isolate->MayNamedAccess(*object, *name, v8::ACCESS_SET)) { | 4166 if (!isolate->MayNamedAccessWrapper(object, name, v8::ACCESS_SET)) { |
| 4194 return SetPropertyWithFailedAccessCheck(object, &lookup, name, value, | 4167 return SetPropertyWithFailedAccessCheck(object, &lookup, name, value, |
| 4195 false, kNonStrictMode); | 4168 false, SLOPPY); |
| 4196 } | 4169 } |
| 4197 } | 4170 } |
| 4198 | 4171 |
| 4199 if (object->IsJSGlobalProxy()) { | 4172 if (object->IsJSGlobalProxy()) { |
| 4200 Handle<Object> proto(object->GetPrototype(), isolate); | 4173 Handle<Object> proto(object->GetPrototype(), isolate); |
| 4201 if (proto->IsNull()) return value; | 4174 if (proto->IsNull()) return value; |
| 4202 ASSERT(proto->IsJSGlobalObject()); | 4175 ASSERT(proto->IsJSGlobalObject()); |
| 4203 return SetLocalPropertyIgnoreAttributes(Handle<JSObject>::cast(proto), | 4176 return SetLocalPropertyIgnoreAttributes(Handle<JSObject>::cast(proto), |
| 4204 name, value, attributes, value_type, mode, extensibility_check); | 4177 name, value, attributes, value_type, mode, extensibility_check); |
| 4205 } | 4178 } |
| 4206 | 4179 |
| 4207 if (lookup.IsFound() && | 4180 if (lookup.IsFound() && |
| 4208 (lookup.type() == INTERCEPTOR || lookup.type() == CALLBACKS)) { | 4181 (lookup.type() == INTERCEPTOR || lookup.type() == CALLBACKS)) { |
| 4209 object->LocalLookupRealNamedProperty(*name, &lookup); | 4182 object->LocalLookupRealNamedProperty(*name, &lookup); |
| 4210 } | 4183 } |
| 4211 | 4184 |
| 4212 // Check for accessor in prototype chain removed here in clone. | 4185 // Check for accessor in prototype chain removed here in clone. |
| 4213 if (!lookup.IsFound()) { | 4186 if (!lookup.IsFound()) { |
| 4214 object->map()->LookupTransition(*object, *name, &lookup); | 4187 object->map()->LookupTransition(*object, *name, &lookup); |
| 4215 TransitionFlag flag = lookup.IsFound() | 4188 TransitionFlag flag = lookup.IsFound() |
| 4216 ? OMIT_TRANSITION : INSERT_TRANSITION; | 4189 ? OMIT_TRANSITION : INSERT_TRANSITION; |
| 4217 // Neither properties nor transitions found. | 4190 // Neither properties nor transitions found. |
| 4218 return AddProperty(object, name, value, attributes, kNonStrictMode, | 4191 return AddProperty(object, name, value, attributes, SLOPPY, |
| 4219 MAY_BE_STORE_FROM_KEYED, extensibility_check, value_type, mode, flag); | 4192 MAY_BE_STORE_FROM_KEYED, extensibility_check, value_type, mode, flag); |
| 4220 } | 4193 } |
| 4221 | 4194 |
| 4222 Handle<Object> old_value = isolate->factory()->the_hole_value(); | 4195 Handle<Object> old_value = isolate->factory()->the_hole_value(); |
| 4223 PropertyAttributes old_attributes = ABSENT; | 4196 PropertyAttributes old_attributes = ABSENT; |
| 4224 bool is_observed = FLAG_harmony_observation && | 4197 bool is_observed = object->map()->is_observed() && |
| 4225 object->map()->is_observed() && | |
| 4226 *name != isolate->heap()->hidden_string(); | 4198 *name != isolate->heap()->hidden_string(); |
| 4227 if (is_observed && lookup.IsProperty()) { | 4199 if (is_observed && lookup.IsProperty()) { |
| 4228 if (lookup.IsDataProperty()) old_value = | 4200 if (lookup.IsDataProperty()) old_value = |
| 4229 Object::GetProperty(object, name); | 4201 Object::GetProperty(object, name); |
| 4230 old_attributes = lookup.GetAttributes(); | 4202 old_attributes = lookup.GetAttributes(); |
| 4231 } | 4203 } |
| 4232 | 4204 |
| 4233 // Check of IsReadOnly removed from here in clone. | 4205 // Check of IsReadOnly removed from here in clone. |
| 4234 switch (lookup.type()) { | 4206 switch (lookup.type()) { |
| 4235 case NORMAL: | 4207 case NORMAL: |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4280 EnqueueChangeRecord(object, "update", name, old_value); | 4252 EnqueueChangeRecord(object, "update", name, old_value); |
| 4281 } | 4253 } |
| 4282 } | 4254 } |
| 4283 } | 4255 } |
| 4284 | 4256 |
| 4285 return value; | 4257 return value; |
| 4286 } | 4258 } |
| 4287 | 4259 |
| 4288 | 4260 |
| 4289 PropertyAttributes JSObject::GetPropertyAttributePostInterceptor( | 4261 PropertyAttributes JSObject::GetPropertyAttributePostInterceptor( |
| 4290 JSObject* receiver, | 4262 Handle<JSObject> object, |
| 4291 Name* name, | 4263 Handle<JSObject> receiver, |
| 4292 bool continue_search) { | 4264 Handle<Name> name, |
| 4265 bool continue_search) { |
| 4293 // Check local property, ignore interceptor. | 4266 // Check local property, ignore interceptor. |
| 4294 LookupResult result(GetIsolate()); | 4267 Isolate* isolate = object->GetIsolate(); |
| 4295 LocalLookupRealNamedProperty(name, &result); | 4268 LookupResult result(isolate); |
| 4269 object->LocalLookupRealNamedProperty(*name, &result); |
| 4296 if (result.IsFound()) return result.GetAttributes(); | 4270 if (result.IsFound()) return result.GetAttributes(); |
| 4297 | 4271 |
| 4298 if (continue_search) { | 4272 if (continue_search) { |
| 4299 // Continue searching via the prototype chain. | 4273 // Continue searching via the prototype chain. |
| 4300 Object* pt = GetPrototype(); | 4274 Handle<Object> proto(object->GetPrototype(), isolate); |
| 4301 if (!pt->IsNull()) { | 4275 if (!proto->IsNull()) { |
| 4302 return JSObject::cast(pt)-> | 4276 return JSReceiver::GetPropertyAttributeWithReceiver( |
| 4303 GetPropertyAttributeWithReceiver(receiver, name); | 4277 Handle<JSObject>::cast(proto), receiver, name); |
| 4304 } | 4278 } |
| 4305 } | 4279 } |
| 4306 return ABSENT; | 4280 return ABSENT; |
| 4307 } | 4281 } |
| 4308 | 4282 |
| 4309 | 4283 |
| 4310 PropertyAttributes JSObject::GetPropertyAttributeWithInterceptor( | 4284 PropertyAttributes JSObject::GetPropertyAttributeWithInterceptor( |
| 4311 JSObject* receiver, | 4285 Handle<JSObject> object, |
| 4312 Name* name, | 4286 Handle<JSObject> receiver, |
| 4313 bool continue_search) { | 4287 Handle<Name> name, |
| 4288 bool continue_search) { |
| 4314 // TODO(rossberg): Support symbols in the API. | 4289 // TODO(rossberg): Support symbols in the API. |
| 4315 if (name->IsSymbol()) return ABSENT; | 4290 if (name->IsSymbol()) return ABSENT; |
| 4316 | 4291 |
| 4317 Isolate* isolate = GetIsolate(); | 4292 Isolate* isolate = object->GetIsolate(); |
| 4318 HandleScope scope(isolate); | 4293 HandleScope scope(isolate); |
| 4319 | 4294 |
| 4320 // Make sure that the top context does not change when doing | 4295 // Make sure that the top context does not change when doing |
| 4321 // callbacks or interceptor calls. | 4296 // callbacks or interceptor calls. |
| 4322 AssertNoContextChange ncc(isolate); | 4297 AssertNoContextChange ncc(isolate); |
| 4323 | 4298 |
| 4324 Handle<InterceptorInfo> interceptor(GetNamedInterceptor()); | 4299 Handle<InterceptorInfo> interceptor(object->GetNamedInterceptor()); |
| 4325 Handle<JSObject> receiver_handle(receiver); | 4300 PropertyCallbackArguments args( |
| 4326 Handle<JSObject> holder_handle(this); | 4301 isolate, interceptor->data(), *receiver, *object); |
| 4327 Handle<String> name_handle(String::cast(name)); | |
| 4328 PropertyCallbackArguments args(isolate, interceptor->data(), receiver, this); | |
| 4329 if (!interceptor->query()->IsUndefined()) { | 4302 if (!interceptor->query()->IsUndefined()) { |
| 4330 v8::NamedPropertyQueryCallback query = | 4303 v8::NamedPropertyQueryCallback query = |
| 4331 v8::ToCData<v8::NamedPropertyQueryCallback>(interceptor->query()); | 4304 v8::ToCData<v8::NamedPropertyQueryCallback>(interceptor->query()); |
| 4332 LOG(isolate, | 4305 LOG(isolate, |
| 4333 ApiNamedPropertyAccess("interceptor-named-has", *holder_handle, name)); | 4306 ApiNamedPropertyAccess("interceptor-named-has", *object, *name)); |
| 4334 v8::Handle<v8::Integer> result = | 4307 v8::Handle<v8::Integer> result = |
| 4335 args.Call(query, v8::Utils::ToLocal(name_handle)); | 4308 args.Call(query, v8::Utils::ToLocal(Handle<String>::cast(name))); |
| 4336 if (!result.IsEmpty()) { | 4309 if (!result.IsEmpty()) { |
| 4337 ASSERT(result->IsInt32()); | 4310 ASSERT(result->IsInt32()); |
| 4338 return static_cast<PropertyAttributes>(result->Int32Value()); | 4311 return static_cast<PropertyAttributes>(result->Int32Value()); |
| 4339 } | 4312 } |
| 4340 } else if (!interceptor->getter()->IsUndefined()) { | 4313 } else if (!interceptor->getter()->IsUndefined()) { |
| 4341 v8::NamedPropertyGetterCallback getter = | 4314 v8::NamedPropertyGetterCallback getter = |
| 4342 v8::ToCData<v8::NamedPropertyGetterCallback>(interceptor->getter()); | 4315 v8::ToCData<v8::NamedPropertyGetterCallback>(interceptor->getter()); |
| 4343 LOG(isolate, | 4316 LOG(isolate, |
| 4344 ApiNamedPropertyAccess("interceptor-named-get-has", this, name)); | 4317 ApiNamedPropertyAccess("interceptor-named-get-has", *object, *name)); |
| 4345 v8::Handle<v8::Value> result = | 4318 v8::Handle<v8::Value> result = |
| 4346 args.Call(getter, v8::Utils::ToLocal(name_handle)); | 4319 args.Call(getter, v8::Utils::ToLocal(Handle<String>::cast(name))); |
| 4347 if (!result.IsEmpty()) return DONT_ENUM; | 4320 if (!result.IsEmpty()) return DONT_ENUM; |
| 4348 } | 4321 } |
| 4349 return holder_handle->GetPropertyAttributePostInterceptor(*receiver_handle, | 4322 return GetPropertyAttributePostInterceptor( |
| 4350 *name_handle, | 4323 object, receiver, name, continue_search); |
| 4351 continue_search); | |
| 4352 } | 4324 } |
| 4353 | 4325 |
| 4354 | 4326 |
| 4355 PropertyAttributes JSReceiver::GetPropertyAttributeWithReceiver( | 4327 PropertyAttributes JSReceiver::GetPropertyAttributeWithReceiver( |
| 4356 JSReceiver* receiver, | 4328 Handle<JSReceiver> object, |
| 4357 Name* key) { | 4329 Handle<JSReceiver> receiver, |
| 4330 Handle<Name> key) { |
| 4358 uint32_t index = 0; | 4331 uint32_t index = 0; |
| 4359 if (IsJSObject() && key->AsArrayIndex(&index)) { | 4332 if (object->IsJSObject() && key->AsArrayIndex(&index)) { |
| 4360 return JSObject::cast(this)->GetElementAttributeWithReceiver( | 4333 return JSObject::GetElementAttributeWithReceiver( |
| 4361 receiver, index, true); | 4334 Handle<JSObject>::cast(object), receiver, index, true); |
| 4362 } | 4335 } |
| 4363 // Named property. | 4336 // Named property. |
| 4364 LookupResult lookup(GetIsolate()); | 4337 LookupResult lookup(object->GetIsolate()); |
| 4365 Lookup(key, &lookup); | 4338 object->Lookup(*key, &lookup); |
| 4366 return GetPropertyAttributeForResult(receiver, &lookup, key, true); | 4339 return GetPropertyAttributeForResult(object, receiver, &lookup, key, true); |
| 4367 } | 4340 } |
| 4368 | 4341 |
| 4369 | 4342 |
| 4370 PropertyAttributes JSReceiver::GetPropertyAttributeForResult( | 4343 PropertyAttributes JSReceiver::GetPropertyAttributeForResult( |
| 4371 JSReceiver* receiver, | 4344 Handle<JSReceiver> object, |
| 4345 Handle<JSReceiver> receiver, |
| 4372 LookupResult* lookup, | 4346 LookupResult* lookup, |
| 4373 Name* name, | 4347 Handle<Name> name, |
| 4374 bool continue_search) { | 4348 bool continue_search) { |
| 4375 // Check access rights if needed. | 4349 // Check access rights if needed. |
| 4376 if (IsAccessCheckNeeded()) { | 4350 if (object->IsAccessCheckNeeded()) { |
| 4377 JSObject* this_obj = JSObject::cast(this); | 4351 Heap* heap = object->GetHeap(); |
| 4378 Heap* heap = GetHeap(); | 4352 Handle<JSObject> obj = Handle<JSObject>::cast(object); |
| 4379 if (!heap->isolate()->MayNamedAccess(this_obj, name, v8::ACCESS_HAS)) { | 4353 if (!heap->isolate()->MayNamedAccessWrapper(obj, name, v8::ACCESS_HAS)) { |
| 4380 return this_obj->GetPropertyAttributeWithFailedAccessCheck( | 4354 return JSObject::GetPropertyAttributeWithFailedAccessCheck( |
| 4381 receiver, lookup, name, continue_search); | 4355 obj, lookup, name, continue_search); |
| 4382 } | 4356 } |
| 4383 } | 4357 } |
| 4384 if (lookup->IsFound()) { | 4358 if (lookup->IsFound()) { |
| 4385 switch (lookup->type()) { | 4359 switch (lookup->type()) { |
| 4386 case NORMAL: // fall through | 4360 case NORMAL: // fall through |
| 4387 case FIELD: | 4361 case FIELD: |
| 4388 case CONSTANT: | 4362 case CONSTANT: |
| 4389 case CALLBACKS: | 4363 case CALLBACKS: |
| 4390 return lookup->GetAttributes(); | 4364 return lookup->GetAttributes(); |
| 4391 case HANDLER: { | 4365 case HANDLER: { |
| 4392 return JSProxy::cast(lookup->proxy())->GetPropertyAttributeWithHandler( | 4366 return JSProxy::GetPropertyAttributeWithHandler( |
| 4393 receiver, name); | 4367 handle(lookup->proxy()), receiver, name); |
| 4394 } | 4368 } |
| 4395 case INTERCEPTOR: | 4369 case INTERCEPTOR: |
| 4396 return lookup->holder()->GetPropertyAttributeWithInterceptor( | 4370 return JSObject::GetPropertyAttributeWithInterceptor( |
| 4397 JSObject::cast(receiver), name, continue_search); | 4371 handle(lookup->holder()), |
| 4372 Handle<JSObject>::cast(receiver), |
| 4373 name, |
| 4374 continue_search); |
| 4398 case TRANSITION: | 4375 case TRANSITION: |
| 4399 case NONEXISTENT: | 4376 case NONEXISTENT: |
| 4400 UNREACHABLE(); | 4377 UNREACHABLE(); |
| 4401 } | 4378 } |
| 4402 } | 4379 } |
| 4403 return ABSENT; | 4380 return ABSENT; |
| 4404 } | 4381 } |
| 4405 | 4382 |
| 4406 | 4383 |
| 4407 PropertyAttributes JSReceiver::GetLocalPropertyAttribute(Name* name) { | 4384 PropertyAttributes JSReceiver::GetLocalPropertyAttribute( |
| 4385 Handle<JSReceiver> object, Handle<Name> name) { |
| 4408 // Check whether the name is an array index. | 4386 // Check whether the name is an array index. |
| 4409 uint32_t index = 0; | 4387 uint32_t index = 0; |
| 4410 if (IsJSObject() && name->AsArrayIndex(&index)) { | 4388 if (object->IsJSObject() && name->AsArrayIndex(&index)) { |
| 4411 return GetLocalElementAttribute(index); | 4389 return GetLocalElementAttribute(object, index); |
| 4412 } | 4390 } |
| 4413 // Named property. | 4391 // Named property. |
| 4414 LookupResult lookup(GetIsolate()); | 4392 LookupResult lookup(object->GetIsolate()); |
| 4415 LocalLookup(name, &lookup, true); | 4393 object->LocalLookup(*name, &lookup, true); |
| 4416 return GetPropertyAttributeForResult(this, &lookup, name, false); | 4394 return GetPropertyAttributeForResult(object, object, &lookup, name, false); |
| 4417 } | 4395 } |
| 4418 | 4396 |
| 4419 | 4397 |
| 4420 PropertyAttributes JSObject::GetElementAttributeWithReceiver( | 4398 PropertyAttributes JSObject::GetElementAttributeWithReceiver( |
| 4421 JSReceiver* receiver, uint32_t index, bool continue_search) { | 4399 Handle<JSObject> object, |
| 4422 Isolate* isolate = GetIsolate(); | 4400 Handle<JSReceiver> receiver, |
| 4401 uint32_t index, |
| 4402 bool continue_search) { |
| 4403 Isolate* isolate = object->GetIsolate(); |
| 4423 | 4404 |
| 4424 // Check access rights if needed. | 4405 // Check access rights if needed. |
| 4425 if (IsAccessCheckNeeded()) { | 4406 if (object->IsAccessCheckNeeded()) { |
| 4426 if (!isolate->MayIndexedAccess(this, index, v8::ACCESS_HAS)) { | 4407 if (!isolate->MayIndexedAccessWrapper(object, index, v8::ACCESS_HAS)) { |
| 4427 isolate->ReportFailedAccessCheck(this, v8::ACCESS_HAS); | 4408 isolate->ReportFailedAccessCheckWrapper(object, v8::ACCESS_HAS); |
| 4428 return ABSENT; | 4409 return ABSENT; |
| 4429 } | 4410 } |
| 4430 } | 4411 } |
| 4431 | 4412 |
| 4432 if (IsJSGlobalProxy()) { | 4413 if (object->IsJSGlobalProxy()) { |
| 4433 Object* proto = GetPrototype(); | 4414 Handle<Object> proto(object->GetPrototype(), isolate); |
| 4434 if (proto->IsNull()) return ABSENT; | 4415 if (proto->IsNull()) return ABSENT; |
| 4435 ASSERT(proto->IsJSGlobalObject()); | 4416 ASSERT(proto->IsJSGlobalObject()); |
| 4436 return JSObject::cast(proto)->GetElementAttributeWithReceiver( | 4417 return JSObject::GetElementAttributeWithReceiver( |
| 4437 receiver, index, continue_search); | 4418 Handle<JSObject>::cast(proto), receiver, index, continue_search); |
| 4438 } | 4419 } |
| 4439 | 4420 |
| 4440 // Check for lookup interceptor except when bootstrapping. | 4421 // Check for lookup interceptor except when bootstrapping. |
| 4441 if (HasIndexedInterceptor() && !isolate->bootstrapper()->IsActive()) { | 4422 if (object->HasIndexedInterceptor() && !isolate->bootstrapper()->IsActive()) { |
| 4442 return GetElementAttributeWithInterceptor(receiver, index, continue_search); | 4423 return JSObject::GetElementAttributeWithInterceptor( |
| 4424 object, receiver, index, continue_search); |
| 4443 } | 4425 } |
| 4444 | 4426 |
| 4445 return GetElementAttributeWithoutInterceptor( | 4427 return GetElementAttributeWithoutInterceptor( |
| 4446 receiver, index, continue_search); | 4428 object, receiver, index, continue_search); |
| 4447 } | 4429 } |
| 4448 | 4430 |
| 4449 | 4431 |
| 4450 PropertyAttributes JSObject::GetElementAttributeWithInterceptor( | 4432 PropertyAttributes JSObject::GetElementAttributeWithInterceptor( |
| 4451 JSReceiver* receiver, uint32_t index, bool continue_search) { | 4433 Handle<JSObject> object, |
| 4452 Isolate* isolate = GetIsolate(); | 4434 Handle<JSReceiver> receiver, |
| 4435 uint32_t index, |
| 4436 bool continue_search) { |
| 4437 Isolate* isolate = object->GetIsolate(); |
| 4453 HandleScope scope(isolate); | 4438 HandleScope scope(isolate); |
| 4454 | 4439 |
| 4455 // Make sure that the top context does not change when doing | 4440 // Make sure that the top context does not change when doing |
| 4456 // callbacks or interceptor calls. | 4441 // callbacks or interceptor calls. |
| 4457 AssertNoContextChange ncc(isolate); | 4442 AssertNoContextChange ncc(isolate); |
| 4458 | 4443 |
| 4459 Handle<InterceptorInfo> interceptor(GetIndexedInterceptor()); | 4444 Handle<InterceptorInfo> interceptor(object->GetIndexedInterceptor()); |
| 4460 Handle<JSReceiver> hreceiver(receiver); | 4445 PropertyCallbackArguments args( |
| 4461 Handle<JSObject> holder(this); | 4446 isolate, interceptor->data(), *receiver, *object); |
| 4462 PropertyCallbackArguments args(isolate, interceptor->data(), receiver, this); | |
| 4463 if (!interceptor->query()->IsUndefined()) { | 4447 if (!interceptor->query()->IsUndefined()) { |
| 4464 v8::IndexedPropertyQueryCallback query = | 4448 v8::IndexedPropertyQueryCallback query = |
| 4465 v8::ToCData<v8::IndexedPropertyQueryCallback>(interceptor->query()); | 4449 v8::ToCData<v8::IndexedPropertyQueryCallback>(interceptor->query()); |
| 4466 LOG(isolate, | 4450 LOG(isolate, |
| 4467 ApiIndexedPropertyAccess("interceptor-indexed-has", this, index)); | 4451 ApiIndexedPropertyAccess("interceptor-indexed-has", *object, index)); |
| 4468 v8::Handle<v8::Integer> result = args.Call(query, index); | 4452 v8::Handle<v8::Integer> result = args.Call(query, index); |
| 4469 if (!result.IsEmpty()) | 4453 if (!result.IsEmpty()) |
| 4470 return static_cast<PropertyAttributes>(result->Int32Value()); | 4454 return static_cast<PropertyAttributes>(result->Int32Value()); |
| 4471 } else if (!interceptor->getter()->IsUndefined()) { | 4455 } else if (!interceptor->getter()->IsUndefined()) { |
| 4472 v8::IndexedPropertyGetterCallback getter = | 4456 v8::IndexedPropertyGetterCallback getter = |
| 4473 v8::ToCData<v8::IndexedPropertyGetterCallback>(interceptor->getter()); | 4457 v8::ToCData<v8::IndexedPropertyGetterCallback>(interceptor->getter()); |
| 4474 LOG(isolate, | 4458 LOG(isolate, |
| 4475 ApiIndexedPropertyAccess("interceptor-indexed-get-has", this, index)); | 4459 ApiIndexedPropertyAccess( |
| 4460 "interceptor-indexed-get-has", *object, index)); |
| 4476 v8::Handle<v8::Value> result = args.Call(getter, index); | 4461 v8::Handle<v8::Value> result = args.Call(getter, index); |
| 4477 if (!result.IsEmpty()) return NONE; | 4462 if (!result.IsEmpty()) return NONE; |
| 4478 } | 4463 } |
| 4479 | 4464 |
| 4480 return holder->GetElementAttributeWithoutInterceptor( | 4465 return GetElementAttributeWithoutInterceptor( |
| 4481 *hreceiver, index, continue_search); | 4466 object, receiver, index, continue_search); |
| 4482 } | 4467 } |
| 4483 | 4468 |
| 4484 | 4469 |
| 4485 PropertyAttributes JSObject::GetElementAttributeWithoutInterceptor( | 4470 PropertyAttributes JSObject::GetElementAttributeWithoutInterceptor( |
| 4486 JSReceiver* receiver, uint32_t index, bool continue_search) { | 4471 Handle<JSObject> object, |
| 4487 PropertyAttributes attr = GetElementsAccessor()->GetAttributes( | 4472 Handle<JSReceiver> receiver, |
| 4488 receiver, this, index); | 4473 uint32_t index, |
| 4474 bool continue_search) { |
| 4475 PropertyAttributes attr = object->GetElementsAccessor()->GetAttributes( |
| 4476 *receiver, *object, index); |
| 4489 if (attr != ABSENT) return attr; | 4477 if (attr != ABSENT) return attr; |
| 4490 | 4478 |
| 4491 // Handle [] on String objects. | 4479 // Handle [] on String objects. |
| 4492 if (IsStringObjectWithCharacterAt(index)) { | 4480 if (object->IsStringObjectWithCharacterAt(index)) { |
| 4493 return static_cast<PropertyAttributes>(READ_ONLY | DONT_DELETE); | 4481 return static_cast<PropertyAttributes>(READ_ONLY | DONT_DELETE); |
| 4494 } | 4482 } |
| 4495 | 4483 |
| 4496 if (!continue_search) return ABSENT; | 4484 if (!continue_search) return ABSENT; |
| 4497 | 4485 |
| 4498 Object* pt = GetPrototype(); | 4486 Handle<Object> proto(object->GetPrototype(), object->GetIsolate()); |
| 4499 if (pt->IsJSProxy()) { | 4487 if (proto->IsJSProxy()) { |
| 4500 // We need to follow the spec and simulate a call to [[GetOwnProperty]]. | 4488 // We need to follow the spec and simulate a call to [[GetOwnProperty]]. |
| 4501 return JSProxy::cast(pt)->GetElementAttributeWithHandler(receiver, index); | 4489 return JSProxy::GetElementAttributeWithHandler( |
| 4490 Handle<JSProxy>::cast(proto), receiver, index); |
| 4502 } | 4491 } |
| 4503 if (pt->IsNull()) return ABSENT; | 4492 if (proto->IsNull()) return ABSENT; |
| 4504 return JSObject::cast(pt)->GetElementAttributeWithReceiver( | 4493 return GetElementAttributeWithReceiver( |
| 4505 receiver, index, true); | 4494 Handle<JSObject>::cast(proto), receiver, index, true); |
| 4506 } | 4495 } |
| 4507 | 4496 |
| 4508 | 4497 |
| 4509 Handle<Map> NormalizedMapCache::Get(Handle<NormalizedMapCache> cache, | 4498 Handle<Map> NormalizedMapCache::Get(Handle<NormalizedMapCache> cache, |
| 4510 Handle<JSObject> obj, | 4499 Handle<JSObject> obj, |
| 4511 PropertyNormalizationMode mode) { | 4500 PropertyNormalizationMode mode) { |
| 4512 int index = obj->map()->Hash() % kEntries; | 4501 int index = obj->map()->Hash() % kEntries; |
| 4513 Handle<Object> result = handle(cache->get(index), cache->GetIsolate()); | 4502 Handle<Object> result = handle(cache->get(index), cache->GetIsolate()); |
| 4514 if (result->IsMap() && | 4503 if (result->IsMap() && |
| 4515 Handle<Map>::cast(result)->EquivalentToForNormalization(obj->map(), | 4504 Handle<Map>::cast(result)->EquivalentToForNormalization(obj->map(), |
| (...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4738 } | 4727 } |
| 4739 | 4728 |
| 4740 | 4729 |
| 4741 MaybeObject* JSObject::NormalizeElements() { | 4730 MaybeObject* JSObject::NormalizeElements() { |
| 4742 ASSERT(!HasExternalArrayElements()); | 4731 ASSERT(!HasExternalArrayElements()); |
| 4743 | 4732 |
| 4744 // Find the backing store. | 4733 // Find the backing store. |
| 4745 FixedArrayBase* array = FixedArrayBase::cast(elements()); | 4734 FixedArrayBase* array = FixedArrayBase::cast(elements()); |
| 4746 Map* old_map = array->map(); | 4735 Map* old_map = array->map(); |
| 4747 bool is_arguments = | 4736 bool is_arguments = |
| 4748 (old_map == old_map->GetHeap()->non_strict_arguments_elements_map()); | 4737 (old_map == old_map->GetHeap()->sloppy_arguments_elements_map()); |
| 4749 if (is_arguments) { | 4738 if (is_arguments) { |
| 4750 array = FixedArrayBase::cast(FixedArray::cast(array)->get(1)); | 4739 array = FixedArrayBase::cast(FixedArray::cast(array)->get(1)); |
| 4751 } | 4740 } |
| 4752 if (array->IsDictionary()) return array; | 4741 if (array->IsDictionary()) return array; |
| 4753 | 4742 |
| 4754 ASSERT(HasFastSmiOrObjectElements() || | 4743 ASSERT(HasFastSmiOrObjectElements() || |
| 4755 HasFastDoubleElements() || | 4744 HasFastDoubleElements() || |
| 4756 HasFastArgumentsElements()); | 4745 HasFastArgumentsElements()); |
| 4757 // Compute the effective length and allocate a new backing store. | 4746 // Compute the effective length and allocate a new backing store. |
| 4758 int length = IsJSArray() | 4747 int length = IsJSArray() |
| (...skipping 14 matching lines...) Expand all Loading... |
| 4773 // Switch to using the dictionary as the backing storage for elements. | 4762 // Switch to using the dictionary as the backing storage for elements. |
| 4774 if (is_arguments) { | 4763 if (is_arguments) { |
| 4775 FixedArray::cast(elements())->set(1, dictionary); | 4764 FixedArray::cast(elements())->set(1, dictionary); |
| 4776 } else { | 4765 } else { |
| 4777 // Set the new map first to satify the elements type assert in | 4766 // Set the new map first to satify the elements type assert in |
| 4778 // set_elements(). | 4767 // set_elements(). |
| 4779 Map* new_map; | 4768 Map* new_map; |
| 4780 MaybeObject* maybe = GetElementsTransitionMap(GetIsolate(), | 4769 MaybeObject* maybe = GetElementsTransitionMap(GetIsolate(), |
| 4781 DICTIONARY_ELEMENTS); | 4770 DICTIONARY_ELEMENTS); |
| 4782 if (!maybe->To(&new_map)) return maybe; | 4771 if (!maybe->To(&new_map)) return maybe; |
| 4772 // TODO(verwaest): Replace by MigrateToMap. |
| 4783 set_map(new_map); | 4773 set_map(new_map); |
| 4784 set_elements(dictionary); | 4774 set_elements(dictionary); |
| 4785 } | 4775 } |
| 4786 | 4776 |
| 4787 old_map->GetHeap()->isolate()->counters()->elements_to_dictionary()-> | 4777 old_map->GetHeap()->isolate()->counters()->elements_to_dictionary()-> |
| 4788 Increment(); | 4778 Increment(); |
| 4789 | 4779 |
| 4790 #ifdef DEBUG | 4780 #ifdef DEBUG |
| 4791 if (FLAG_trace_normalization) { | 4781 if (FLAG_trace_normalization) { |
| 4792 PrintF("Object elements have been normalized:\n"); | 4782 PrintF("Object elements have been normalized:\n"); |
| (...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4953 | 4943 |
| 4954 // We never delete (inline-stored) identity hashes. | 4944 // We never delete (inline-stored) identity hashes. |
| 4955 ASSERT(*key != *isolate->factory()->identity_hash_string()); | 4945 ASSERT(*key != *isolate->factory()->identity_hash_string()); |
| 4956 if (inline_value->IsUndefined() || inline_value->IsSmi()) return; | 4946 if (inline_value->IsUndefined() || inline_value->IsSmi()) return; |
| 4957 | 4947 |
| 4958 Handle<ObjectHashTable> hashtable(ObjectHashTable::cast(inline_value)); | 4948 Handle<ObjectHashTable> hashtable(ObjectHashTable::cast(inline_value)); |
| 4959 ObjectHashTable::Put(hashtable, key, isolate->factory()->the_hole_value()); | 4949 ObjectHashTable::Put(hashtable, key, isolate->factory()->the_hole_value()); |
| 4960 } | 4950 } |
| 4961 | 4951 |
| 4962 | 4952 |
| 4963 bool JSObject::HasHiddenProperties() { | 4953 bool JSObject::HasHiddenProperties(Handle<JSObject> object) { |
| 4964 return GetPropertyAttributePostInterceptor(this, | 4954 Handle<Name> hidden = object->GetIsolate()->factory()->hidden_string(); |
| 4965 GetHeap()->hidden_string(), | 4955 return GetPropertyAttributePostInterceptor( |
| 4966 false) != ABSENT; | 4956 object, object, hidden, false) != ABSENT; |
| 4967 } | 4957 } |
| 4968 | 4958 |
| 4969 | 4959 |
| 4970 Object* JSObject::GetHiddenPropertiesHashTable() { | 4960 Object* JSObject::GetHiddenPropertiesHashTable() { |
| 4971 ASSERT(!IsJSGlobalProxy()); | 4961 ASSERT(!IsJSGlobalProxy()); |
| 4972 if (HasFastProperties()) { | 4962 if (HasFastProperties()) { |
| 4973 // If the object has fast properties, check whether the first slot | 4963 // If the object has fast properties, check whether the first slot |
| 4974 // in the descriptor array matches the hidden string. Since the | 4964 // in the descriptor array matches the hidden string. Since the |
| 4975 // hidden strings hash code is zero (and no other name has hash | 4965 // hidden strings hash code is zero (and no other name has hash |
| 4976 // code zero) it will always occupy the first entry if present. | 4966 // code zero) it will always occupy the first entry if present. |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5037 | 5027 |
| 5038 | 5028 |
| 5039 Handle<Object> JSObject::SetHiddenPropertiesHashTable(Handle<JSObject> object, | 5029 Handle<Object> JSObject::SetHiddenPropertiesHashTable(Handle<JSObject> object, |
| 5040 Handle<Object> value) { | 5030 Handle<Object> value) { |
| 5041 ASSERT(!object->IsJSGlobalProxy()); | 5031 ASSERT(!object->IsJSGlobalProxy()); |
| 5042 | 5032 |
| 5043 Isolate* isolate = object->GetIsolate(); | 5033 Isolate* isolate = object->GetIsolate(); |
| 5044 | 5034 |
| 5045 // We can store the identity hash inline iff there is no backing store | 5035 // We can store the identity hash inline iff there is no backing store |
| 5046 // for hidden properties yet. | 5036 // for hidden properties yet. |
| 5047 ASSERT(object->HasHiddenProperties() != value->IsSmi()); | 5037 ASSERT(JSObject::HasHiddenProperties(object) != value->IsSmi()); |
| 5048 if (object->HasFastProperties()) { | 5038 if (object->HasFastProperties()) { |
| 5049 // If the object has fast properties, check whether the first slot | 5039 // If the object has fast properties, check whether the first slot |
| 5050 // in the descriptor array matches the hidden string. Since the | 5040 // in the descriptor array matches the hidden string. Since the |
| 5051 // hidden strings hash code is zero (and no other name has hash | 5041 // hidden strings hash code is zero (and no other name has hash |
| 5052 // code zero) it will always occupy the first entry if present. | 5042 // code zero) it will always occupy the first entry if present. |
| 5053 DescriptorArray* descriptors = object->map()->instance_descriptors(); | 5043 DescriptorArray* descriptors = object->map()->instance_descriptors(); |
| 5054 if (descriptors->number_of_descriptors() > 0) { | 5044 if (descriptors->number_of_descriptors() > 0) { |
| 5055 int sorted_index = descriptors->GetSortedKeyIndex(0); | 5045 int sorted_index = descriptors->GetSortedKeyIndex(0); |
| 5056 if (descriptors->GetKey(sorted_index) == isolate->heap()->hidden_string() | 5046 if (descriptors->GetKey(sorted_index) == isolate->heap()->hidden_string() |
| 5057 && sorted_index < object->map()->NumberOfOwnDescriptors()) { | 5047 && sorted_index < object->map()->NumberOfOwnDescriptors()) { |
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5168 | 5158 |
| 5169 | 5159 |
| 5170 Handle<Object> JSObject::DeleteElement(Handle<JSObject> object, | 5160 Handle<Object> JSObject::DeleteElement(Handle<JSObject> object, |
| 5171 uint32_t index, | 5161 uint32_t index, |
| 5172 DeleteMode mode) { | 5162 DeleteMode mode) { |
| 5173 Isolate* isolate = object->GetIsolate(); | 5163 Isolate* isolate = object->GetIsolate(); |
| 5174 Factory* factory = isolate->factory(); | 5164 Factory* factory = isolate->factory(); |
| 5175 | 5165 |
| 5176 // Check access rights if needed. | 5166 // Check access rights if needed. |
| 5177 if (object->IsAccessCheckNeeded() && | 5167 if (object->IsAccessCheckNeeded() && |
| 5178 !isolate->MayIndexedAccess(*object, index, v8::ACCESS_DELETE)) { | 5168 !isolate->MayIndexedAccessWrapper(object, index, v8::ACCESS_DELETE)) { |
| 5179 isolate->ReportFailedAccessCheck(*object, v8::ACCESS_DELETE); | 5169 isolate->ReportFailedAccessCheckWrapper(object, v8::ACCESS_DELETE); |
| 5180 RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object); | 5170 RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object); |
| 5181 return factory->false_value(); | 5171 return factory->false_value(); |
| 5182 } | 5172 } |
| 5183 | 5173 |
| 5184 if (object->IsStringObjectWithCharacterAt(index)) { | 5174 if (object->IsStringObjectWithCharacterAt(index)) { |
| 5185 if (mode == STRICT_DELETION) { | 5175 if (mode == STRICT_DELETION) { |
| 5186 // Deleting a non-configurable property in strict mode. | 5176 // Deleting a non-configurable property in strict mode. |
| 5187 Handle<Object> name = factory->NewNumberFromUint(index); | 5177 Handle<Object> name = factory->NewNumberFromUint(index); |
| 5188 Handle<Object> args[2] = { name, object }; | 5178 Handle<Object> args[2] = { name, object }; |
| 5189 Handle<Object> error = | 5179 Handle<Object> error = |
| 5190 factory->NewTypeError("strict_delete_property", | 5180 factory->NewTypeError("strict_delete_property", |
| 5191 HandleVector(args, 2)); | 5181 HandleVector(args, 2)); |
| 5192 isolate->Throw(*error); | 5182 isolate->Throw(*error); |
| 5193 return Handle<Object>(); | 5183 return Handle<Object>(); |
| 5194 } | 5184 } |
| 5195 return factory->false_value(); | 5185 return factory->false_value(); |
| 5196 } | 5186 } |
| 5197 | 5187 |
| 5198 if (object->IsJSGlobalProxy()) { | 5188 if (object->IsJSGlobalProxy()) { |
| 5199 Handle<Object> proto(object->GetPrototype(), isolate); | 5189 Handle<Object> proto(object->GetPrototype(), isolate); |
| 5200 if (proto->IsNull()) return factory->false_value(); | 5190 if (proto->IsNull()) return factory->false_value(); |
| 5201 ASSERT(proto->IsJSGlobalObject()); | 5191 ASSERT(proto->IsJSGlobalObject()); |
| 5202 return DeleteElement(Handle<JSObject>::cast(proto), index, mode); | 5192 return DeleteElement(Handle<JSObject>::cast(proto), index, mode); |
| 5203 } | 5193 } |
| 5204 | 5194 |
| 5205 Handle<Object> old_value; | 5195 Handle<Object> old_value; |
| 5206 bool should_enqueue_change_record = false; | 5196 bool should_enqueue_change_record = false; |
| 5207 if (FLAG_harmony_observation && object->map()->is_observed()) { | 5197 if (object->map()->is_observed()) { |
| 5208 should_enqueue_change_record = HasLocalElement(object, index); | 5198 should_enqueue_change_record = HasLocalElement(object, index); |
| 5209 if (should_enqueue_change_record) { | 5199 if (should_enqueue_change_record) { |
| 5210 old_value = object->GetLocalElementAccessorPair(index) != NULL | 5200 old_value = object->GetLocalElementAccessorPair(index) != NULL |
| 5211 ? Handle<Object>::cast(factory->the_hole_value()) | 5201 ? Handle<Object>::cast(factory->the_hole_value()) |
| 5212 : Object::GetElement(isolate, object, index); | 5202 : Object::GetElement(isolate, object, index); |
| 5213 } | 5203 } |
| 5214 } | 5204 } |
| 5215 | 5205 |
| 5216 // Skip interceptor if forcing deletion. | 5206 // Skip interceptor if forcing deletion. |
| 5217 Handle<Object> result; | 5207 Handle<Object> result; |
| (...skipping 14 matching lines...) Expand all Loading... |
| 5232 | 5222 |
| 5233 Handle<Object> JSObject::DeleteProperty(Handle<JSObject> object, | 5223 Handle<Object> JSObject::DeleteProperty(Handle<JSObject> object, |
| 5234 Handle<Name> name, | 5224 Handle<Name> name, |
| 5235 DeleteMode mode) { | 5225 DeleteMode mode) { |
| 5236 Isolate* isolate = object->GetIsolate(); | 5226 Isolate* isolate = object->GetIsolate(); |
| 5237 // ECMA-262, 3rd, 8.6.2.5 | 5227 // ECMA-262, 3rd, 8.6.2.5 |
| 5238 ASSERT(name->IsName()); | 5228 ASSERT(name->IsName()); |
| 5239 | 5229 |
| 5240 // Check access rights if needed. | 5230 // Check access rights if needed. |
| 5241 if (object->IsAccessCheckNeeded() && | 5231 if (object->IsAccessCheckNeeded() && |
| 5242 !isolate->MayNamedAccess(*object, *name, v8::ACCESS_DELETE)) { | 5232 !isolate->MayNamedAccessWrapper(object, name, v8::ACCESS_DELETE)) { |
| 5243 isolate->ReportFailedAccessCheck(*object, v8::ACCESS_DELETE); | 5233 isolate->ReportFailedAccessCheckWrapper(object, v8::ACCESS_DELETE); |
| 5244 RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object); | 5234 RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object); |
| 5245 return isolate->factory()->false_value(); | 5235 return isolate->factory()->false_value(); |
| 5246 } | 5236 } |
| 5247 | 5237 |
| 5248 if (object->IsJSGlobalProxy()) { | 5238 if (object->IsJSGlobalProxy()) { |
| 5249 Object* proto = object->GetPrototype(); | 5239 Object* proto = object->GetPrototype(); |
| 5250 if (proto->IsNull()) return isolate->factory()->false_value(); | 5240 if (proto->IsNull()) return isolate->factory()->false_value(); |
| 5251 ASSERT(proto->IsJSGlobalObject()); | 5241 ASSERT(proto->IsJSGlobalObject()); |
| 5252 return JSGlobalObject::DeleteProperty( | 5242 return JSGlobalObject::DeleteProperty( |
| 5253 handle(JSGlobalObject::cast(proto)), name, mode); | 5243 handle(JSGlobalObject::cast(proto)), name, mode); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 5268 Handle<Object> args[2] = { name, object }; | 5258 Handle<Object> args[2] = { name, object }; |
| 5269 Handle<Object> error = isolate->factory()->NewTypeError( | 5259 Handle<Object> error = isolate->factory()->NewTypeError( |
| 5270 "strict_delete_property", HandleVector(args, ARRAY_SIZE(args))); | 5260 "strict_delete_property", HandleVector(args, ARRAY_SIZE(args))); |
| 5271 isolate->Throw(*error); | 5261 isolate->Throw(*error); |
| 5272 return Handle<Object>(); | 5262 return Handle<Object>(); |
| 5273 } | 5263 } |
| 5274 return isolate->factory()->false_value(); | 5264 return isolate->factory()->false_value(); |
| 5275 } | 5265 } |
| 5276 | 5266 |
| 5277 Handle<Object> old_value = isolate->factory()->the_hole_value(); | 5267 Handle<Object> old_value = isolate->factory()->the_hole_value(); |
| 5278 bool is_observed = FLAG_harmony_observation && | 5268 bool is_observed = object->map()->is_observed() && |
| 5279 object->map()->is_observed() && | |
| 5280 *name != isolate->heap()->hidden_string(); | 5269 *name != isolate->heap()->hidden_string(); |
| 5281 if (is_observed && lookup.IsDataProperty()) { | 5270 if (is_observed && lookup.IsDataProperty()) { |
| 5282 old_value = Object::GetProperty(object, name); | 5271 old_value = Object::GetProperty(object, name); |
| 5283 } | 5272 } |
| 5284 Handle<Object> result; | 5273 Handle<Object> result; |
| 5285 | 5274 |
| 5286 // Check for interceptor. | 5275 // Check for interceptor. |
| 5287 if (lookup.IsInterceptor()) { | 5276 if (lookup.IsInterceptor()) { |
| 5288 // Skip interceptor if forcing a deletion. | 5277 // Skip interceptor if forcing a deletion. |
| 5289 if (mode == FORCE_DELETION) { | 5278 if (mode == FORCE_DELETION) { |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5391 case FAST_SMI_ELEMENTS: | 5380 case FAST_SMI_ELEMENTS: |
| 5392 case FAST_HOLEY_SMI_ELEMENTS: | 5381 case FAST_HOLEY_SMI_ELEMENTS: |
| 5393 break; | 5382 break; |
| 5394 case FAST_ELEMENTS: | 5383 case FAST_ELEMENTS: |
| 5395 case FAST_HOLEY_ELEMENTS: | 5384 case FAST_HOLEY_ELEMENTS: |
| 5396 case DICTIONARY_ELEMENTS: { | 5385 case DICTIONARY_ELEMENTS: { |
| 5397 FixedArray* elements = FixedArray::cast(this->elements()); | 5386 FixedArray* elements = FixedArray::cast(this->elements()); |
| 5398 if (ReferencesObjectFromElements(elements, kind, obj)) return true; | 5387 if (ReferencesObjectFromElements(elements, kind, obj)) return true; |
| 5399 break; | 5388 break; |
| 5400 } | 5389 } |
| 5401 case NON_STRICT_ARGUMENTS_ELEMENTS: { | 5390 case SLOPPY_ARGUMENTS_ELEMENTS: { |
| 5402 FixedArray* parameter_map = FixedArray::cast(elements()); | 5391 FixedArray* parameter_map = FixedArray::cast(elements()); |
| 5403 // Check the mapped parameters. | 5392 // Check the mapped parameters. |
| 5404 int length = parameter_map->length(); | 5393 int length = parameter_map->length(); |
| 5405 for (int i = 2; i < length; ++i) { | 5394 for (int i = 2; i < length; ++i) { |
| 5406 Object* value = parameter_map->get(i); | 5395 Object* value = parameter_map->get(i); |
| 5407 if (!value->IsTheHole() && value == obj) return true; | 5396 if (!value->IsTheHole() && value == obj) return true; |
| 5408 } | 5397 } |
| 5409 // Check the arguments. | 5398 // Check the arguments. |
| 5410 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); | 5399 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); |
| 5411 kind = arguments->IsDictionary() ? DICTIONARY_ELEMENTS : | 5400 kind = arguments->IsDictionary() ? DICTIONARY_ELEMENTS : |
| 5412 FAST_HOLEY_ELEMENTS; | 5401 FAST_HOLEY_ELEMENTS; |
| 5413 if (ReferencesObjectFromElements(arguments, kind, obj)) return true; | 5402 if (ReferencesObjectFromElements(arguments, kind, obj)) return true; |
| 5414 break; | 5403 break; |
| 5415 } | 5404 } |
| 5416 } | 5405 } |
| 5417 | 5406 |
| 5418 // For functions check the context. | 5407 // For functions check the context. |
| 5419 if (IsJSFunction()) { | 5408 if (IsJSFunction()) { |
| 5420 // Get the constructor function for arguments array. | 5409 // Get the constructor function for arguments array. |
| 5421 JSObject* arguments_boilerplate = | 5410 JSObject* arguments_boilerplate = |
| 5422 heap->isolate()->context()->native_context()-> | 5411 heap->isolate()->context()->native_context()-> |
| 5423 arguments_boilerplate(); | 5412 sloppy_arguments_boilerplate(); |
| 5424 JSFunction* arguments_function = | 5413 JSFunction* arguments_function = |
| 5425 JSFunction::cast(arguments_boilerplate->map()->constructor()); | 5414 JSFunction::cast(arguments_boilerplate->map()->constructor()); |
| 5426 | 5415 |
| 5427 // Get the context and don't check if it is the native context. | 5416 // Get the context and don't check if it is the native context. |
| 5428 JSFunction* f = JSFunction::cast(this); | 5417 JSFunction* f = JSFunction::cast(this); |
| 5429 Context* context = f->context(); | 5418 Context* context = f->context(); |
| 5430 if (context->IsNativeContext()) { | 5419 if (context->IsNativeContext()) { |
| 5431 return false; | 5420 return false; |
| 5432 } | 5421 } |
| 5433 | 5422 |
| (...skipping 29 matching lines...) Expand all Loading... |
| 5463 return false; | 5452 return false; |
| 5464 } | 5453 } |
| 5465 | 5454 |
| 5466 | 5455 |
| 5467 Handle<Object> JSObject::PreventExtensions(Handle<JSObject> object) { | 5456 Handle<Object> JSObject::PreventExtensions(Handle<JSObject> object) { |
| 5468 Isolate* isolate = object->GetIsolate(); | 5457 Isolate* isolate = object->GetIsolate(); |
| 5469 | 5458 |
| 5470 if (!object->map()->is_extensible()) return object; | 5459 if (!object->map()->is_extensible()) return object; |
| 5471 | 5460 |
| 5472 if (object->IsAccessCheckNeeded() && | 5461 if (object->IsAccessCheckNeeded() && |
| 5473 !isolate->MayNamedAccess(*object, | 5462 !isolate->MayNamedAccessWrapper(object, |
| 5474 isolate->heap()->undefined_value(), | 5463 isolate->factory()->undefined_value(), |
| 5475 v8::ACCESS_KEYS)) { | 5464 v8::ACCESS_KEYS)) { |
| 5476 isolate->ReportFailedAccessCheck(*object, v8::ACCESS_KEYS); | 5465 isolate->ReportFailedAccessCheckWrapper(object, v8::ACCESS_KEYS); |
| 5477 RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object); | 5466 RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object); |
| 5478 return isolate->factory()->false_value(); | 5467 return isolate->factory()->false_value(); |
| 5479 } | 5468 } |
| 5480 | 5469 |
| 5481 if (object->IsJSGlobalProxy()) { | 5470 if (object->IsJSGlobalProxy()) { |
| 5482 Handle<Object> proto(object->GetPrototype(), isolate); | 5471 Handle<Object> proto(object->GetPrototype(), isolate); |
| 5483 if (proto->IsNull()) return object; | 5472 if (proto->IsNull()) return object; |
| 5484 ASSERT(proto->IsJSGlobalObject()); | 5473 ASSERT(proto->IsJSGlobalObject()); |
| 5485 return PreventExtensions(Handle<JSObject>::cast(proto)); | 5474 return PreventExtensions(Handle<JSObject>::cast(proto)); |
| 5486 } | 5475 } |
| (...skipping 15 matching lines...) Expand all Loading... |
| 5502 | 5491 |
| 5503 // Make sure that we never go back to fast case. | 5492 // Make sure that we never go back to fast case. |
| 5504 dictionary->set_requires_slow_elements(); | 5493 dictionary->set_requires_slow_elements(); |
| 5505 | 5494 |
| 5506 // Do a map transition, other objects with this map may still | 5495 // Do a map transition, other objects with this map may still |
| 5507 // be extensible. | 5496 // be extensible. |
| 5508 // TODO(adamk): Extend the NormalizedMapCache to handle non-extensible maps. | 5497 // TODO(adamk): Extend the NormalizedMapCache to handle non-extensible maps. |
| 5509 Handle<Map> new_map = Map::Copy(handle(object->map())); | 5498 Handle<Map> new_map = Map::Copy(handle(object->map())); |
| 5510 | 5499 |
| 5511 new_map->set_is_extensible(false); | 5500 new_map->set_is_extensible(false); |
| 5512 object->set_map(*new_map); | 5501 JSObject::MigrateToMap(object, new_map); |
| 5513 ASSERT(!object->map()->is_extensible()); | 5502 ASSERT(!object->map()->is_extensible()); |
| 5514 | 5503 |
| 5515 if (FLAG_harmony_observation && object->map()->is_observed()) { | 5504 if (object->map()->is_observed()) { |
| 5516 EnqueueChangeRecord(object, "preventExtensions", Handle<Name>(), | 5505 EnqueueChangeRecord(object, "preventExtensions", Handle<Name>(), |
| 5517 isolate->factory()->the_hole_value()); | 5506 isolate->factory()->the_hole_value()); |
| 5518 } | 5507 } |
| 5519 return object; | 5508 return object; |
| 5520 } | 5509 } |
| 5521 | 5510 |
| 5522 | 5511 |
| 5523 template<typename Dictionary> | 5512 template<typename Dictionary> |
| 5524 static void FreezeDictionary(Dictionary* dictionary) { | 5513 static void FreezeDictionary(Dictionary* dictionary) { |
| 5525 int capacity = dictionary->Capacity(); | 5514 int capacity = dictionary->Capacity(); |
| 5526 for (int i = 0; i < capacity; i++) { | 5515 for (int i = 0; i < capacity; i++) { |
| 5527 Object* k = dictionary->KeyAt(i); | 5516 Object* k = dictionary->KeyAt(i); |
| 5528 if (dictionary->IsKey(k)) { | 5517 if (dictionary->IsKey(k)) { |
| 5529 PropertyDetails details = dictionary->DetailsAt(i); | 5518 PropertyDetails details = dictionary->DetailsAt(i); |
| 5530 int attrs = DONT_DELETE; | 5519 int attrs = DONT_DELETE; |
| 5531 // READ_ONLY is an invalid attribute for JS setters/getters. | 5520 // READ_ONLY is an invalid attribute for JS setters/getters. |
| 5532 if (details.type() != CALLBACKS || | 5521 if (details.type() != CALLBACKS || |
| 5533 !dictionary->ValueAt(i)->IsAccessorPair()) { | 5522 !dictionary->ValueAt(i)->IsAccessorPair()) { |
| 5534 attrs |= READ_ONLY; | 5523 attrs |= READ_ONLY; |
| 5535 } | 5524 } |
| 5536 details = details.CopyAddAttributes( | 5525 details = details.CopyAddAttributes( |
| 5537 static_cast<PropertyAttributes>(attrs)); | 5526 static_cast<PropertyAttributes>(attrs)); |
| 5538 dictionary->DetailsAtPut(i, details); | 5527 dictionary->DetailsAtPut(i, details); |
| 5539 } | 5528 } |
| 5540 } | 5529 } |
| 5541 } | 5530 } |
| 5542 | 5531 |
| 5543 | 5532 |
| 5544 Handle<Object> JSObject::Freeze(Handle<JSObject> object) { | 5533 Handle<Object> JSObject::Freeze(Handle<JSObject> object) { |
| 5545 // Freezing non-strict arguments should be handled elsewhere. | 5534 // Freezing sloppy arguments should be handled elsewhere. |
| 5546 ASSERT(!object->HasNonStrictArgumentsElements()); | 5535 ASSERT(!object->HasSloppyArgumentsElements()); |
| 5547 ASSERT(!object->map()->is_observed()); | 5536 ASSERT(!object->map()->is_observed()); |
| 5548 | 5537 |
| 5549 if (object->map()->is_frozen()) return object; | 5538 if (object->map()->is_frozen()) return object; |
| 5550 | 5539 |
| 5551 Isolate* isolate = object->GetIsolate(); | 5540 Isolate* isolate = object->GetIsolate(); |
| 5552 if (object->IsAccessCheckNeeded() && | 5541 if (object->IsAccessCheckNeeded() && |
| 5553 !isolate->MayNamedAccess(*object, | 5542 !isolate->MayNamedAccessWrapper(object, |
| 5554 isolate->heap()->undefined_value(), | 5543 isolate->factory()->undefined_value(), |
| 5555 v8::ACCESS_KEYS)) { | 5544 v8::ACCESS_KEYS)) { |
| 5556 isolate->ReportFailedAccessCheck(*object, v8::ACCESS_KEYS); | 5545 isolate->ReportFailedAccessCheckWrapper(object, v8::ACCESS_KEYS); |
| 5557 RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object); | 5546 RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object); |
| 5558 return isolate->factory()->false_value(); | 5547 return isolate->factory()->false_value(); |
| 5559 } | 5548 } |
| 5560 | 5549 |
| 5561 if (object->IsJSGlobalProxy()) { | 5550 if (object->IsJSGlobalProxy()) { |
| 5562 Handle<Object> proto(object->GetPrototype(), isolate); | 5551 Handle<Object> proto(object->GetPrototype(), isolate); |
| 5563 if (proto->IsNull()) return object; | 5552 if (proto->IsNull()) return object; |
| 5564 ASSERT(proto->IsJSGlobalObject()); | 5553 ASSERT(proto->IsJSGlobalObject()); |
| 5565 return Freeze(Handle<JSObject>::cast(proto)); | 5554 return Freeze(Handle<JSObject>::cast(proto)); |
| 5566 } | 5555 } |
| (...skipping 28 matching lines...) Expand all Loading... |
| 5595 // No existing elements, use a pre-allocated empty backing store | 5584 // No existing elements, use a pre-allocated empty backing store |
| 5596 new_element_dictionary = | 5585 new_element_dictionary = |
| 5597 isolate->factory()->empty_slow_element_dictionary(); | 5586 isolate->factory()->empty_slow_element_dictionary(); |
| 5598 } | 5587 } |
| 5599 } | 5588 } |
| 5600 | 5589 |
| 5601 LookupResult result(isolate); | 5590 LookupResult result(isolate); |
| 5602 Handle<Map> old_map(object->map()); | 5591 Handle<Map> old_map(object->map()); |
| 5603 old_map->LookupTransition(*object, isolate->heap()->frozen_symbol(), &result); | 5592 old_map->LookupTransition(*object, isolate->heap()->frozen_symbol(), &result); |
| 5604 if (result.IsTransition()) { | 5593 if (result.IsTransition()) { |
| 5605 Map* transition_map = result.GetTransitionTarget(); | 5594 Handle<Map> transition_map(result.GetTransitionTarget()); |
| 5606 ASSERT(transition_map->has_dictionary_elements()); | 5595 ASSERT(transition_map->has_dictionary_elements()); |
| 5607 ASSERT(transition_map->is_frozen()); | 5596 ASSERT(transition_map->is_frozen()); |
| 5608 ASSERT(!transition_map->is_extensible()); | 5597 ASSERT(!transition_map->is_extensible()); |
| 5609 object->set_map(transition_map); | 5598 JSObject::MigrateToMap(object, transition_map); |
| 5610 } else if (object->HasFastProperties() && old_map->CanHaveMoreTransitions()) { | 5599 } else if (object->HasFastProperties() && old_map->CanHaveMoreTransitions()) { |
| 5611 // Create a new descriptor array with fully-frozen properties | 5600 // Create a new descriptor array with fully-frozen properties |
| 5612 int num_descriptors = old_map->NumberOfOwnDescriptors(); | 5601 int num_descriptors = old_map->NumberOfOwnDescriptors(); |
| 5613 Handle<DescriptorArray> new_descriptors = | 5602 Handle<DescriptorArray> new_descriptors = |
| 5614 DescriptorArray::CopyUpToAddAttributes( | 5603 DescriptorArray::CopyUpToAddAttributes( |
| 5615 handle(old_map->instance_descriptors()), num_descriptors, FROZEN); | 5604 handle(old_map->instance_descriptors()), num_descriptors, FROZEN); |
| 5616 Handle<Map> new_map = Map::CopyReplaceDescriptors( | 5605 Handle<Map> new_map = Map::CopyReplaceDescriptors( |
| 5617 old_map, new_descriptors, INSERT_TRANSITION, | 5606 old_map, new_descriptors, INSERT_TRANSITION, |
| 5618 isolate->factory()->frozen_symbol()); | 5607 isolate->factory()->frozen_symbol()); |
| 5619 new_map->freeze(); | 5608 new_map->freeze(); |
| 5620 new_map->set_is_extensible(false); | 5609 new_map->set_is_extensible(false); |
| 5621 new_map->set_elements_kind(DICTIONARY_ELEMENTS); | 5610 new_map->set_elements_kind(DICTIONARY_ELEMENTS); |
| 5622 object->set_map(*new_map); | 5611 JSObject::MigrateToMap(object, new_map); |
| 5623 } else { | 5612 } else { |
| 5624 // Slow path: need to normalize properties for safety | 5613 // Slow path: need to normalize properties for safety |
| 5625 NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0); | 5614 NormalizeProperties(object, CLEAR_INOBJECT_PROPERTIES, 0); |
| 5626 | 5615 |
| 5627 // Create a new map, since other objects with this map may be extensible. | 5616 // Create a new map, since other objects with this map may be extensible. |
| 5628 // TODO(adamk): Extend the NormalizedMapCache to handle non-extensible maps. | 5617 // TODO(adamk): Extend the NormalizedMapCache to handle non-extensible maps. |
| 5629 Handle<Map> new_map = Map::Copy(handle(object->map())); | 5618 Handle<Map> new_map = Map::Copy(handle(object->map())); |
| 5630 new_map->freeze(); | 5619 new_map->freeze(); |
| 5631 new_map->set_is_extensible(false); | 5620 new_map->set_is_extensible(false); |
| 5632 new_map->set_elements_kind(DICTIONARY_ELEMENTS); | 5621 new_map->set_elements_kind(DICTIONARY_ELEMENTS); |
| 5633 object->set_map(*new_map); | 5622 JSObject::MigrateToMap(object, new_map); |
| 5634 | 5623 |
| 5635 // Freeze dictionary-mode properties | 5624 // Freeze dictionary-mode properties |
| 5636 FreezeDictionary(object->property_dictionary()); | 5625 FreezeDictionary(object->property_dictionary()); |
| 5637 } | 5626 } |
| 5638 | 5627 |
| 5639 ASSERT(object->map()->has_dictionary_elements()); | 5628 ASSERT(object->map()->has_dictionary_elements()); |
| 5640 if (!new_element_dictionary.is_null()) { | 5629 if (!new_element_dictionary.is_null()) { |
| 5641 object->set_elements(*new_element_dictionary); | 5630 object->set_elements(*new_element_dictionary); |
| 5642 } | 5631 } |
| 5643 | 5632 |
| (...skipping 23 matching lines...) Expand all Loading... |
| 5667 Handle<Map> new_map; | 5656 Handle<Map> new_map; |
| 5668 if (result.IsTransition()) { | 5657 if (result.IsTransition()) { |
| 5669 new_map = handle(result.GetTransitionTarget()); | 5658 new_map = handle(result.GetTransitionTarget()); |
| 5670 ASSERT(new_map->is_observed()); | 5659 ASSERT(new_map->is_observed()); |
| 5671 } else if (object->map()->CanHaveMoreTransitions()) { | 5660 } else if (object->map()->CanHaveMoreTransitions()) { |
| 5672 new_map = Map::CopyForObserved(handle(object->map())); | 5661 new_map = Map::CopyForObserved(handle(object->map())); |
| 5673 } else { | 5662 } else { |
| 5674 new_map = Map::Copy(handle(object->map())); | 5663 new_map = Map::Copy(handle(object->map())); |
| 5675 new_map->set_is_observed(); | 5664 new_map->set_is_observed(); |
| 5676 } | 5665 } |
| 5677 object->set_map(*new_map); | 5666 JSObject::MigrateToMap(object, new_map); |
| 5678 } | 5667 } |
| 5679 | 5668 |
| 5680 | 5669 |
| 5681 Handle<JSObject> JSObject::Copy(Handle<JSObject> object) { | 5670 Handle<JSObject> JSObject::Copy(Handle<JSObject> object) { |
| 5682 Isolate* isolate = object->GetIsolate(); | 5671 Isolate* isolate = object->GetIsolate(); |
| 5683 CALL_HEAP_FUNCTION(isolate, | 5672 CALL_HEAP_FUNCTION(isolate, |
| 5684 isolate->heap()->CopyJSObject(*object), JSObject); | 5673 isolate->heap()->CopyJSObject(*object), JSObject); |
| 5685 } | 5674 } |
| 5686 | 5675 |
| 5687 | 5676 |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5788 } | 5777 } |
| 5789 } | 5778 } |
| 5790 } else { | 5779 } else { |
| 5791 Handle<FixedArray> names = | 5780 Handle<FixedArray> names = |
| 5792 isolate->factory()->NewFixedArray(copy->NumberOfLocalProperties()); | 5781 isolate->factory()->NewFixedArray(copy->NumberOfLocalProperties()); |
| 5793 copy->GetLocalPropertyNames(*names, 0); | 5782 copy->GetLocalPropertyNames(*names, 0); |
| 5794 for (int i = 0; i < names->length(); i++) { | 5783 for (int i = 0; i < names->length(); i++) { |
| 5795 ASSERT(names->get(i)->IsString()); | 5784 ASSERT(names->get(i)->IsString()); |
| 5796 Handle<String> key_string(String::cast(names->get(i))); | 5785 Handle<String> key_string(String::cast(names->get(i))); |
| 5797 PropertyAttributes attributes = | 5786 PropertyAttributes attributes = |
| 5798 copy->GetLocalPropertyAttribute(*key_string); | 5787 JSReceiver::GetLocalPropertyAttribute(copy, key_string); |
| 5799 // Only deep copy fields from the object literal expression. | 5788 // Only deep copy fields from the object literal expression. |
| 5800 // In particular, don't try to copy the length attribute of | 5789 // In particular, don't try to copy the length attribute of |
| 5801 // an array. | 5790 // an array. |
| 5802 if (attributes != NONE) continue; | 5791 if (attributes != NONE) continue; |
| 5803 Handle<Object> value( | 5792 Handle<Object> value( |
| 5804 copy->GetProperty(*key_string, &attributes)->ToObjectUnchecked(), | 5793 copy->GetProperty(*key_string, &attributes)->ToObjectUnchecked(), |
| 5805 isolate); | 5794 isolate); |
| 5806 if (value->IsJSObject()) { | 5795 if (value->IsJSObject()) { |
| 5807 Handle<JSObject> result = VisitElementOrProperty( | 5796 Handle<JSObject> result = VisitElementOrProperty( |
| 5808 copy, Handle<JSObject>::cast(value)); | 5797 copy, Handle<JSObject>::cast(value)); |
| 5809 RETURN_IF_EMPTY_HANDLE_VALUE(isolate, result, Handle<JSObject>()); | 5798 RETURN_IF_EMPTY_HANDLE_VALUE(isolate, result, Handle<JSObject>()); |
| 5810 if (copying) { | 5799 if (copying) { |
| 5811 // Creating object copy for literals. No strict mode needed. | 5800 // Creating object copy for literals. No strict mode needed. |
| 5812 CHECK_NOT_EMPTY_HANDLE(isolate, JSObject::SetProperty( | 5801 CHECK_NOT_EMPTY_HANDLE(isolate, JSObject::SetProperty( |
| 5813 copy, key_string, result, NONE, kNonStrictMode)); | 5802 copy, key_string, result, NONE, SLOPPY)); |
| 5814 } | 5803 } |
| 5815 } | 5804 } |
| 5816 } | 5805 } |
| 5817 } | 5806 } |
| 5818 | 5807 |
| 5819 // Deep copy local elements. | 5808 // Deep copy local elements. |
| 5820 // Pixel elements cannot be created using an object literal. | 5809 // Pixel elements cannot be created using an object literal. |
| 5821 ASSERT(!copy->HasExternalArrayElements()); | 5810 ASSERT(!copy->HasExternalArrayElements()); |
| 5822 switch (kind) { | 5811 switch (kind) { |
| 5823 case FAST_SMI_ELEMENTS: | 5812 case FAST_SMI_ELEMENTS: |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5862 copy, Handle<JSObject>::cast(value)); | 5851 copy, Handle<JSObject>::cast(value)); |
| 5863 RETURN_IF_EMPTY_HANDLE_VALUE(isolate, result, Handle<JSObject>()); | 5852 RETURN_IF_EMPTY_HANDLE_VALUE(isolate, result, Handle<JSObject>()); |
| 5864 if (copying) { | 5853 if (copying) { |
| 5865 element_dictionary->ValueAtPut(i, *result); | 5854 element_dictionary->ValueAtPut(i, *result); |
| 5866 } | 5855 } |
| 5867 } | 5856 } |
| 5868 } | 5857 } |
| 5869 } | 5858 } |
| 5870 break; | 5859 break; |
| 5871 } | 5860 } |
| 5872 case NON_STRICT_ARGUMENTS_ELEMENTS: | 5861 case SLOPPY_ARGUMENTS_ELEMENTS: |
| 5873 UNIMPLEMENTED(); | 5862 UNIMPLEMENTED(); |
| 5874 break; | 5863 break; |
| 5875 | 5864 |
| 5876 | 5865 |
| 5877 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \ | 5866 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \ |
| 5878 case EXTERNAL_##TYPE##_ELEMENTS: \ | 5867 case EXTERNAL_##TYPE##_ELEMENTS: \ |
| 5879 case TYPE##_ELEMENTS: \ | 5868 case TYPE##_ELEMENTS: \ |
| 5880 | 5869 |
| 5881 TYPED_ARRAYS(TYPED_ARRAY_CASE) | 5870 TYPED_ARRAYS(TYPED_ARRAY_CASE) |
| 5882 #undef TYPED_ARRAY_CASE | 5871 #undef TYPED_ARRAY_CASE |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5920 // - No prototype has enumerable properties/elements. | 5909 // - No prototype has enumerable properties/elements. |
| 5921 bool JSReceiver::IsSimpleEnum() { | 5910 bool JSReceiver::IsSimpleEnum() { |
| 5922 Heap* heap = GetHeap(); | 5911 Heap* heap = GetHeap(); |
| 5923 for (Object* o = this; | 5912 for (Object* o = this; |
| 5924 o != heap->null_value(); | 5913 o != heap->null_value(); |
| 5925 o = JSObject::cast(o)->GetPrototype()) { | 5914 o = JSObject::cast(o)->GetPrototype()) { |
| 5926 if (!o->IsJSObject()) return false; | 5915 if (!o->IsJSObject()) return false; |
| 5927 JSObject* curr = JSObject::cast(o); | 5916 JSObject* curr = JSObject::cast(o); |
| 5928 int enum_length = curr->map()->EnumLength(); | 5917 int enum_length = curr->map()->EnumLength(); |
| 5929 if (enum_length == kInvalidEnumCacheSentinel) return false; | 5918 if (enum_length == kInvalidEnumCacheSentinel) return false; |
| 5919 if (curr->IsAccessCheckNeeded()) return false; |
| 5930 ASSERT(!curr->HasNamedInterceptor()); | 5920 ASSERT(!curr->HasNamedInterceptor()); |
| 5931 ASSERT(!curr->HasIndexedInterceptor()); | 5921 ASSERT(!curr->HasIndexedInterceptor()); |
| 5932 ASSERT(!curr->IsAccessCheckNeeded()); | |
| 5933 if (curr->NumberOfEnumElements() > 0) return false; | 5922 if (curr->NumberOfEnumElements() > 0) return false; |
| 5934 if (curr != this && enum_length != 0) return false; | 5923 if (curr != this && enum_length != 0) return false; |
| 5935 } | 5924 } |
| 5936 return true; | 5925 return true; |
| 5937 } | 5926 } |
| 5938 | 5927 |
| 5939 | 5928 |
| 5940 static bool FilterKey(Object* key, PropertyAttributes filter) { | 5929 static bool FilterKey(Object* key, PropertyAttributes filter) { |
| 5941 if ((filter & SYMBOLIC) && key->IsSymbol()) { | 5930 if ((filter & SYMBOLIC) && key->IsSymbol()) { |
| 5942 return true; | 5931 return true; |
| (...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6123 | 6112 |
| 6124 case DICTIONARY_ELEMENTS: | 6113 case DICTIONARY_ELEMENTS: |
| 6125 if (UpdateGetterSetterInDictionary(object->element_dictionary(), | 6114 if (UpdateGetterSetterInDictionary(object->element_dictionary(), |
| 6126 index, | 6115 index, |
| 6127 *getter, | 6116 *getter, |
| 6128 *setter, | 6117 *setter, |
| 6129 attributes)) { | 6118 attributes)) { |
| 6130 return; | 6119 return; |
| 6131 } | 6120 } |
| 6132 break; | 6121 break; |
| 6133 case NON_STRICT_ARGUMENTS_ELEMENTS: { | 6122 case SLOPPY_ARGUMENTS_ELEMENTS: { |
| 6134 // Ascertain whether we have read-only properties or an existing | 6123 // Ascertain whether we have read-only properties or an existing |
| 6135 // getter/setter pair in an arguments elements dictionary backing | 6124 // getter/setter pair in an arguments elements dictionary backing |
| 6136 // store. | 6125 // store. |
| 6137 FixedArray* parameter_map = FixedArray::cast(object->elements()); | 6126 FixedArray* parameter_map = FixedArray::cast(object->elements()); |
| 6138 uint32_t length = parameter_map->length(); | 6127 uint32_t length = parameter_map->length(); |
| 6139 Object* probe = | 6128 Object* probe = |
| 6140 index < (length - 2) ? parameter_map->get(index + 2) : NULL; | 6129 index < (length - 2) ? parameter_map->get(index + 2) : NULL; |
| 6141 if (probe == NULL || probe->IsTheHole()) { | 6130 if (probe == NULL || probe->IsTheHole()) { |
| 6142 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); | 6131 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); |
| 6143 if (arguments->IsDictionary()) { | 6132 if (arguments->IsDictionary()) { |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6206 } | 6195 } |
| 6207 | 6196 |
| 6208 Handle<AccessorPair> accessors = CreateAccessorPairFor(object, name); | 6197 Handle<AccessorPair> accessors = CreateAccessorPairFor(object, name); |
| 6209 accessors->SetComponents(*getter, *setter); | 6198 accessors->SetComponents(*getter, *setter); |
| 6210 accessors->set_access_flags(access_control); | 6199 accessors->set_access_flags(access_control); |
| 6211 | 6200 |
| 6212 SetPropertyCallback(object, name, accessors, attributes); | 6201 SetPropertyCallback(object, name, accessors, attributes); |
| 6213 } | 6202 } |
| 6214 | 6203 |
| 6215 | 6204 |
| 6216 bool JSObject::CanSetCallback(Name* name) { | 6205 bool JSObject::CanSetCallback(Handle<JSObject> object, Handle<Name> name) { |
| 6217 ASSERT(!IsAccessCheckNeeded() || | 6206 Isolate* isolate = object->GetIsolate(); |
| 6218 GetIsolate()->MayNamedAccess(this, name, v8::ACCESS_SET)); | 6207 ASSERT(!object->IsAccessCheckNeeded() || |
| 6208 isolate->MayNamedAccessWrapper(object, name, v8::ACCESS_SET)); |
| 6219 | 6209 |
| 6220 // Check if there is an API defined callback object which prohibits | 6210 // Check if there is an API defined callback object which prohibits |
| 6221 // callback overwriting in this object or its prototype chain. | 6211 // callback overwriting in this object or its prototype chain. |
| 6222 // This mechanism is needed for instance in a browser setting, where | 6212 // This mechanism is needed for instance in a browser setting, where |
| 6223 // certain accessors such as window.location should not be allowed | 6213 // certain accessors such as window.location should not be allowed |
| 6224 // to be overwritten because allowing overwriting could potentially | 6214 // to be overwritten because allowing overwriting could potentially |
| 6225 // cause security problems. | 6215 // cause security problems. |
| 6226 LookupResult callback_result(GetIsolate()); | 6216 LookupResult callback_result(isolate); |
| 6227 LookupCallbackProperty(name, &callback_result); | 6217 object->LookupCallbackProperty(*name, &callback_result); |
| 6228 if (callback_result.IsFound()) { | 6218 if (callback_result.IsFound()) { |
| 6229 Object* obj = callback_result.GetCallbackObject(); | 6219 Object* callback_obj = callback_result.GetCallbackObject(); |
| 6230 if (obj->IsAccessorInfo()) { | 6220 if (callback_obj->IsAccessorInfo()) { |
| 6231 return !AccessorInfo::cast(obj)->prohibits_overwriting(); | 6221 return !AccessorInfo::cast(callback_obj)->prohibits_overwriting(); |
| 6232 } | 6222 } |
| 6233 if (obj->IsAccessorPair()) { | 6223 if (callback_obj->IsAccessorPair()) { |
| 6234 return !AccessorPair::cast(obj)->prohibits_overwriting(); | 6224 return !AccessorPair::cast(callback_obj)->prohibits_overwriting(); |
| 6235 } | 6225 } |
| 6236 } | 6226 } |
| 6237 return true; | 6227 return true; |
| 6238 } | 6228 } |
| 6239 | 6229 |
| 6240 | 6230 |
| 6241 bool Map::DictionaryElementsInPrototypeChainOnly() { | 6231 bool Map::DictionaryElementsInPrototypeChainOnly() { |
| 6242 Heap* heap = GetHeap(); | 6232 Heap* heap = GetHeap(); |
| 6243 | 6233 |
| 6244 if (IsDictionaryElementsKind(elements_kind())) { | 6234 if (IsDictionaryElementsKind(elements_kind())) { |
| (...skipping 29 matching lines...) Expand all Loading... |
| 6274 bool had_dictionary_elements = object->HasDictionaryElements(); | 6264 bool had_dictionary_elements = object->HasDictionaryElements(); |
| 6275 Handle<SeededNumberDictionary> dictionary = NormalizeElements(object); | 6265 Handle<SeededNumberDictionary> dictionary = NormalizeElements(object); |
| 6276 ASSERT(object->HasDictionaryElements() || | 6266 ASSERT(object->HasDictionaryElements() || |
| 6277 object->HasDictionaryArgumentsElements()); | 6267 object->HasDictionaryArgumentsElements()); |
| 6278 // Update the dictionary with the new CALLBACKS property. | 6268 // Update the dictionary with the new CALLBACKS property. |
| 6279 dictionary = SeededNumberDictionary::Set(dictionary, index, structure, | 6269 dictionary = SeededNumberDictionary::Set(dictionary, index, structure, |
| 6280 details); | 6270 details); |
| 6281 dictionary->set_requires_slow_elements(); | 6271 dictionary->set_requires_slow_elements(); |
| 6282 | 6272 |
| 6283 // Update the dictionary backing store on the object. | 6273 // Update the dictionary backing store on the object. |
| 6284 if (object->elements()->map() == heap->non_strict_arguments_elements_map()) { | 6274 if (object->elements()->map() == heap->sloppy_arguments_elements_map()) { |
| 6285 // Also delete any parameter alias. | 6275 // Also delete any parameter alias. |
| 6286 // | 6276 // |
| 6287 // TODO(kmillikin): when deleting the last parameter alias we could | 6277 // TODO(kmillikin): when deleting the last parameter alias we could |
| 6288 // switch to a direct backing store without the parameter map. This | 6278 // switch to a direct backing store without the parameter map. This |
| 6289 // would allow GC of the context. | 6279 // would allow GC of the context. |
| 6290 FixedArray* parameter_map = FixedArray::cast(object->elements()); | 6280 FixedArray* parameter_map = FixedArray::cast(object->elements()); |
| 6291 if (index < static_cast<uint32_t>(parameter_map->length()) - 2) { | 6281 if (index < static_cast<uint32_t>(parameter_map->length()) - 2) { |
| 6292 parameter_map->set(index + 2, heap->the_hole_value()); | 6282 parameter_map->set(index + 2, heap->the_hole_value()); |
| 6293 } | 6283 } |
| 6294 parameter_map->set(1, *dictionary); | 6284 parameter_map->set(1, *dictionary); |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6331 | 6321 |
| 6332 void JSObject::DefineAccessor(Handle<JSObject> object, | 6322 void JSObject::DefineAccessor(Handle<JSObject> object, |
| 6333 Handle<Name> name, | 6323 Handle<Name> name, |
| 6334 Handle<Object> getter, | 6324 Handle<Object> getter, |
| 6335 Handle<Object> setter, | 6325 Handle<Object> setter, |
| 6336 PropertyAttributes attributes, | 6326 PropertyAttributes attributes, |
| 6337 v8::AccessControl access_control) { | 6327 v8::AccessControl access_control) { |
| 6338 Isolate* isolate = object->GetIsolate(); | 6328 Isolate* isolate = object->GetIsolate(); |
| 6339 // Check access rights if needed. | 6329 // Check access rights if needed. |
| 6340 if (object->IsAccessCheckNeeded() && | 6330 if (object->IsAccessCheckNeeded() && |
| 6341 !isolate->MayNamedAccess(*object, *name, v8::ACCESS_SET)) { | 6331 !isolate->MayNamedAccessWrapper(object, name, v8::ACCESS_SET)) { |
| 6342 isolate->ReportFailedAccessCheck(*object, v8::ACCESS_SET); | 6332 isolate->ReportFailedAccessCheckWrapper(object, v8::ACCESS_SET); |
| 6343 return; | 6333 return; |
| 6344 } | 6334 } |
| 6345 | 6335 |
| 6346 if (object->IsJSGlobalProxy()) { | 6336 if (object->IsJSGlobalProxy()) { |
| 6347 Handle<Object> proto(object->GetPrototype(), isolate); | 6337 Handle<Object> proto(object->GetPrototype(), isolate); |
| 6348 if (proto->IsNull()) return; | 6338 if (proto->IsNull()) return; |
| 6349 ASSERT(proto->IsJSGlobalObject()); | 6339 ASSERT(proto->IsJSGlobalObject()); |
| 6350 DefineAccessor(Handle<JSObject>::cast(proto), | 6340 DefineAccessor(Handle<JSObject>::cast(proto), |
| 6351 name, | 6341 name, |
| 6352 getter, | 6342 getter, |
| 6353 setter, | 6343 setter, |
| 6354 attributes, | 6344 attributes, |
| 6355 access_control); | 6345 access_control); |
| 6356 return; | 6346 return; |
| 6357 } | 6347 } |
| 6358 | 6348 |
| 6359 // Make sure that the top context does not change when doing callbacks or | 6349 // Make sure that the top context does not change when doing callbacks or |
| 6360 // interceptor calls. | 6350 // interceptor calls. |
| 6361 AssertNoContextChange ncc(isolate); | 6351 AssertNoContextChange ncc(isolate); |
| 6362 | 6352 |
| 6363 // Try to flatten before operating on the string. | 6353 // Try to flatten before operating on the string. |
| 6364 if (name->IsString()) String::cast(*name)->TryFlatten(); | 6354 if (name->IsString()) String::cast(*name)->TryFlatten(); |
| 6365 | 6355 |
| 6366 if (!object->CanSetCallback(*name)) return; | 6356 if (!JSObject::CanSetCallback(object, name)) return; |
| 6367 | 6357 |
| 6368 uint32_t index = 0; | 6358 uint32_t index = 0; |
| 6369 bool is_element = name->AsArrayIndex(&index); | 6359 bool is_element = name->AsArrayIndex(&index); |
| 6370 | 6360 |
| 6371 Handle<Object> old_value = isolate->factory()->the_hole_value(); | 6361 Handle<Object> old_value = isolate->factory()->the_hole_value(); |
| 6372 bool is_observed = FLAG_harmony_observation && | 6362 bool is_observed = object->map()->is_observed() && |
| 6373 object->map()->is_observed() && | |
| 6374 *name != isolate->heap()->hidden_string(); | 6363 *name != isolate->heap()->hidden_string(); |
| 6375 bool preexists = false; | 6364 bool preexists = false; |
| 6376 if (is_observed) { | 6365 if (is_observed) { |
| 6377 if (is_element) { | 6366 if (is_element) { |
| 6378 preexists = HasLocalElement(object, index); | 6367 preexists = HasLocalElement(object, index); |
| 6379 if (preexists && object->GetLocalElementAccessorPair(index) == NULL) { | 6368 if (preexists && object->GetLocalElementAccessorPair(index) == NULL) { |
| 6380 old_value = Object::GetElement(isolate, object, index); | 6369 old_value = Object::GetElement(isolate, object, index); |
| 6381 } | 6370 } |
| 6382 } else { | 6371 } else { |
| 6383 LookupResult lookup(isolate); | 6372 LookupResult lookup(isolate); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 6397 object, name, getter, setter, attributes, access_control); | 6386 object, name, getter, setter, attributes, access_control); |
| 6398 } | 6387 } |
| 6399 | 6388 |
| 6400 if (is_observed) { | 6389 if (is_observed) { |
| 6401 const char* type = preexists ? "reconfigure" : "add"; | 6390 const char* type = preexists ? "reconfigure" : "add"; |
| 6402 EnqueueChangeRecord(object, type, name, old_value); | 6391 EnqueueChangeRecord(object, type, name, old_value); |
| 6403 } | 6392 } |
| 6404 } | 6393 } |
| 6405 | 6394 |
| 6406 | 6395 |
| 6407 static bool TryAccessorTransition(JSObject* self, | 6396 static bool TryAccessorTransition(Handle<JSObject> self, |
| 6408 Map* transitioned_map, | 6397 Handle<Map> transitioned_map, |
| 6409 int target_descriptor, | 6398 int target_descriptor, |
| 6410 AccessorComponent component, | 6399 AccessorComponent component, |
| 6411 Object* accessor, | 6400 Handle<Object> accessor, |
| 6412 PropertyAttributes attributes) { | 6401 PropertyAttributes attributes) { |
| 6413 DescriptorArray* descs = transitioned_map->instance_descriptors(); | 6402 DescriptorArray* descs = transitioned_map->instance_descriptors(); |
| 6414 PropertyDetails details = descs->GetDetails(target_descriptor); | 6403 PropertyDetails details = descs->GetDetails(target_descriptor); |
| 6415 | 6404 |
| 6416 // If the transition target was not callbacks, fall back to the slow case. | 6405 // If the transition target was not callbacks, fall back to the slow case. |
| 6417 if (details.type() != CALLBACKS) return false; | 6406 if (details.type() != CALLBACKS) return false; |
| 6418 Object* descriptor = descs->GetCallbacksObject(target_descriptor); | 6407 Object* descriptor = descs->GetCallbacksObject(target_descriptor); |
| 6419 if (!descriptor->IsAccessorPair()) return false; | 6408 if (!descriptor->IsAccessorPair()) return false; |
| 6420 | 6409 |
| 6421 Object* target_accessor = AccessorPair::cast(descriptor)->get(component); | 6410 Object* target_accessor = AccessorPair::cast(descriptor)->get(component); |
| 6422 PropertyAttributes target_attributes = details.attributes(); | 6411 PropertyAttributes target_attributes = details.attributes(); |
| 6423 | 6412 |
| 6424 // Reuse transition if adding same accessor with same attributes. | 6413 // Reuse transition if adding same accessor with same attributes. |
| 6425 if (target_accessor == accessor && target_attributes == attributes) { | 6414 if (target_accessor == *accessor && target_attributes == attributes) { |
| 6426 self->set_map(transitioned_map); | 6415 JSObject::MigrateToMap(self, transitioned_map); |
| 6427 return true; | 6416 return true; |
| 6428 } | 6417 } |
| 6429 | 6418 |
| 6430 // If either not the same accessor, or not the same attributes, fall back to | 6419 // If either not the same accessor, or not the same attributes, fall back to |
| 6431 // the slow case. | 6420 // the slow case. |
| 6432 return false; | 6421 return false; |
| 6433 } | 6422 } |
| 6434 | 6423 |
| 6435 | 6424 |
| 6436 static MaybeObject* CopyInsertDescriptor(Map* map, | 6425 static MaybeObject* CopyInsertDescriptor(Map* map, |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6478 } | 6467 } |
| 6479 } else { | 6468 } else { |
| 6480 return false; | 6469 return false; |
| 6481 } | 6470 } |
| 6482 | 6471 |
| 6483 int descriptor_number = result.GetDescriptorIndex(); | 6472 int descriptor_number = result.GetDescriptorIndex(); |
| 6484 | 6473 |
| 6485 object->map()->LookupTransition(*object, *name, &result); | 6474 object->map()->LookupTransition(*object, *name, &result); |
| 6486 | 6475 |
| 6487 if (result.IsFound()) { | 6476 if (result.IsFound()) { |
| 6488 Map* target = result.GetTransitionTarget(); | 6477 Handle<Map> target(result.GetTransitionTarget()); |
| 6489 ASSERT(target->NumberOfOwnDescriptors() == | 6478 ASSERT(target->NumberOfOwnDescriptors() == |
| 6490 object->map()->NumberOfOwnDescriptors()); | 6479 object->map()->NumberOfOwnDescriptors()); |
| 6491 // This works since descriptors are sorted in order of addition. | 6480 // This works since descriptors are sorted in order of addition. |
| 6492 ASSERT(object->map()->instance_descriptors()-> | 6481 ASSERT(object->map()->instance_descriptors()-> |
| 6493 GetKey(descriptor_number) == *name); | 6482 GetKey(descriptor_number) == *name); |
| 6494 return TryAccessorTransition(*object, target, descriptor_number, | 6483 return TryAccessorTransition(object, target, descriptor_number, |
| 6495 component, *accessor, attributes); | 6484 component, accessor, attributes); |
| 6496 } | 6485 } |
| 6497 } else { | 6486 } else { |
| 6498 // If not, lookup a transition. | 6487 // If not, lookup a transition. |
| 6499 object->map()->LookupTransition(*object, *name, &result); | 6488 object->map()->LookupTransition(*object, *name, &result); |
| 6500 | 6489 |
| 6501 // If there is a transition, try to follow it. | 6490 // If there is a transition, try to follow it. |
| 6502 if (result.IsFound()) { | 6491 if (result.IsFound()) { |
| 6503 Map* target = result.GetTransitionTarget(); | 6492 Handle<Map> target(result.GetTransitionTarget()); |
| 6504 int descriptor_number = target->LastAdded(); | 6493 int descriptor_number = target->LastAdded(); |
| 6505 ASSERT(target->instance_descriptors()->GetKey(descriptor_number) | 6494 ASSERT(target->instance_descriptors()->GetKey(descriptor_number) |
| 6506 ->Equals(*name)); | 6495 ->Equals(*name)); |
| 6507 return TryAccessorTransition(*object, target, descriptor_number, | 6496 return TryAccessorTransition(object, target, descriptor_number, |
| 6508 component, *accessor, attributes); | 6497 component, accessor, attributes); |
| 6509 } | 6498 } |
| 6510 } | 6499 } |
| 6511 | 6500 |
| 6512 // If there is no transition yet, add a transition to the a new accessor pair | 6501 // If there is no transition yet, add a transition to the a new accessor pair |
| 6513 // containing the accessor. Allocate a new pair if there were no source | 6502 // containing the accessor. Allocate a new pair if there were no source |
| 6514 // accessors. Otherwise, copy the pair and modify the accessor. | 6503 // accessors. Otherwise, copy the pair and modify the accessor. |
| 6515 Handle<AccessorPair> accessors = source_accessors != NULL | 6504 Handle<AccessorPair> accessors = source_accessors != NULL |
| 6516 ? AccessorPair::Copy(Handle<AccessorPair>(source_accessors)) | 6505 ? AccessorPair::Copy(Handle<AccessorPair>(source_accessors)) |
| 6517 : isolate->factory()->NewAccessorPair(); | 6506 : isolate->factory()->NewAccessorPair(); |
| 6518 accessors->set(component, *accessor); | 6507 accessors->set(component, *accessor); |
| 6519 Handle<Map> new_map = CopyInsertDescriptor(Handle<Map>(object->map()), | 6508 Handle<Map> new_map = CopyInsertDescriptor(Handle<Map>(object->map()), |
| 6520 name, accessors, attributes); | 6509 name, accessors, attributes); |
| 6521 object->set_map(*new_map); | 6510 JSObject::MigrateToMap(object, new_map); |
| 6522 return true; | 6511 return true; |
| 6523 } | 6512 } |
| 6524 | 6513 |
| 6525 | 6514 |
| 6526 Handle<Object> JSObject::SetAccessor(Handle<JSObject> object, | 6515 Handle<Object> JSObject::SetAccessor(Handle<JSObject> object, |
| 6527 Handle<AccessorInfo> info) { | 6516 Handle<AccessorInfo> info) { |
| 6528 Isolate* isolate = object->GetIsolate(); | 6517 Isolate* isolate = object->GetIsolate(); |
| 6529 Factory* factory = isolate->factory(); | 6518 Factory* factory = isolate->factory(); |
| 6530 Handle<Name> name(Name::cast(info->name())); | 6519 Handle<Name> name(Name::cast(info->name())); |
| 6531 | 6520 |
| 6532 // Check access rights if needed. | 6521 // Check access rights if needed. |
| 6533 if (object->IsAccessCheckNeeded() && | 6522 if (object->IsAccessCheckNeeded() && |
| 6534 !isolate->MayNamedAccess(*object, *name, v8::ACCESS_SET)) { | 6523 !isolate->MayNamedAccessWrapper(object, name, v8::ACCESS_SET)) { |
| 6535 isolate->ReportFailedAccessCheck(*object, v8::ACCESS_SET); | 6524 isolate->ReportFailedAccessCheckWrapper(object, v8::ACCESS_SET); |
| 6536 RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object); | 6525 RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object); |
| 6537 return factory->undefined_value(); | 6526 return factory->undefined_value(); |
| 6538 } | 6527 } |
| 6539 | 6528 |
| 6540 if (object->IsJSGlobalProxy()) { | 6529 if (object->IsJSGlobalProxy()) { |
| 6541 Handle<Object> proto(object->GetPrototype(), isolate); | 6530 Handle<Object> proto(object->GetPrototype(), isolate); |
| 6542 if (proto->IsNull()) return object; | 6531 if (proto->IsNull()) return object; |
| 6543 ASSERT(proto->IsJSGlobalObject()); | 6532 ASSERT(proto->IsJSGlobalObject()); |
| 6544 return SetAccessor(Handle<JSObject>::cast(proto), info); | 6533 return SetAccessor(Handle<JSObject>::cast(proto), info); |
| 6545 } | 6534 } |
| 6546 | 6535 |
| 6547 // Make sure that the top context does not change when doing callbacks or | 6536 // Make sure that the top context does not change when doing callbacks or |
| 6548 // interceptor calls. | 6537 // interceptor calls. |
| 6549 AssertNoContextChange ncc(isolate); | 6538 AssertNoContextChange ncc(isolate); |
| 6550 | 6539 |
| 6551 // Try to flatten before operating on the string. | 6540 // Try to flatten before operating on the string. |
| 6552 if (name->IsString()) FlattenString(Handle<String>::cast(name)); | 6541 if (name->IsString()) FlattenString(Handle<String>::cast(name)); |
| 6553 | 6542 |
| 6554 if (!object->CanSetCallback(*name)) return factory->undefined_value(); | 6543 if (!JSObject::CanSetCallback(object, name)) { |
| 6544 return factory->undefined_value(); |
| 6545 } |
| 6555 | 6546 |
| 6556 uint32_t index = 0; | 6547 uint32_t index = 0; |
| 6557 bool is_element = name->AsArrayIndex(&index); | 6548 bool is_element = name->AsArrayIndex(&index); |
| 6558 | 6549 |
| 6559 if (is_element) { | 6550 if (is_element) { |
| 6560 if (object->IsJSArray()) return factory->undefined_value(); | 6551 if (object->IsJSArray()) return factory->undefined_value(); |
| 6561 | 6552 |
| 6562 // Accessors overwrite previous callbacks (cf. with getters/setters). | 6553 // Accessors overwrite previous callbacks (cf. with getters/setters). |
| 6563 switch (object->GetElementsKind()) { | 6554 switch (object->GetElementsKind()) { |
| 6564 case FAST_SMI_ELEMENTS: | 6555 case FAST_SMI_ELEMENTS: |
| 6565 case FAST_ELEMENTS: | 6556 case FAST_ELEMENTS: |
| 6566 case FAST_DOUBLE_ELEMENTS: | 6557 case FAST_DOUBLE_ELEMENTS: |
| 6567 case FAST_HOLEY_SMI_ELEMENTS: | 6558 case FAST_HOLEY_SMI_ELEMENTS: |
| 6568 case FAST_HOLEY_ELEMENTS: | 6559 case FAST_HOLEY_ELEMENTS: |
| 6569 case FAST_HOLEY_DOUBLE_ELEMENTS: | 6560 case FAST_HOLEY_DOUBLE_ELEMENTS: |
| 6570 break; | 6561 break; |
| 6571 | 6562 |
| 6572 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \ | 6563 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \ |
| 6573 case EXTERNAL_##TYPE##_ELEMENTS: \ | 6564 case EXTERNAL_##TYPE##_ELEMENTS: \ |
| 6574 case TYPE##_ELEMENTS: \ | 6565 case TYPE##_ELEMENTS: \ |
| 6575 | 6566 |
| 6576 TYPED_ARRAYS(TYPED_ARRAY_CASE) | 6567 TYPED_ARRAYS(TYPED_ARRAY_CASE) |
| 6577 #undef TYPED_ARRAY_CASE | 6568 #undef TYPED_ARRAY_CASE |
| 6578 // Ignore getters and setters on pixel and external array | 6569 // Ignore getters and setters on pixel and external array |
| 6579 // elements. | 6570 // elements. |
| 6580 return factory->undefined_value(); | 6571 return factory->undefined_value(); |
| 6581 | 6572 |
| 6582 case DICTIONARY_ELEMENTS: | 6573 case DICTIONARY_ELEMENTS: |
| 6583 break; | 6574 break; |
| 6584 case NON_STRICT_ARGUMENTS_ELEMENTS: | 6575 case SLOPPY_ARGUMENTS_ELEMENTS: |
| 6585 UNIMPLEMENTED(); | 6576 UNIMPLEMENTED(); |
| 6586 break; | 6577 break; |
| 6587 } | 6578 } |
| 6588 | 6579 |
| 6589 SetElementCallback(object, index, info, info->property_attributes()); | 6580 SetElementCallback(object, index, info, info->property_attributes()); |
| 6590 } else { | 6581 } else { |
| 6591 // Lookup the name. | 6582 // Lookup the name. |
| 6592 LookupResult result(isolate); | 6583 LookupResult result(isolate); |
| 6593 object->LocalLookup(*name, &result, true); | 6584 object->LocalLookup(*name, &result, true); |
| 6594 // ES5 forbids turning a property into an accessor if it's not | 6585 // ES5 forbids turning a property into an accessor if it's not |
| (...skipping 13 matching lines...) Expand all Loading... |
| 6608 Handle<Name> name, | 6599 Handle<Name> name, |
| 6609 AccessorComponent component) { | 6600 AccessorComponent component) { |
| 6610 Isolate* isolate = object->GetIsolate(); | 6601 Isolate* isolate = object->GetIsolate(); |
| 6611 | 6602 |
| 6612 // Make sure that the top context does not change when doing callbacks or | 6603 // Make sure that the top context does not change when doing callbacks or |
| 6613 // interceptor calls. | 6604 // interceptor calls. |
| 6614 AssertNoContextChange ncc(isolate); | 6605 AssertNoContextChange ncc(isolate); |
| 6615 | 6606 |
| 6616 // Check access rights if needed. | 6607 // Check access rights if needed. |
| 6617 if (object->IsAccessCheckNeeded() && | 6608 if (object->IsAccessCheckNeeded() && |
| 6618 !isolate->MayNamedAccess(*object, *name, v8::ACCESS_HAS)) { | 6609 !isolate->MayNamedAccessWrapper(object, name, v8::ACCESS_HAS)) { |
| 6619 isolate->ReportFailedAccessCheck(*object, v8::ACCESS_HAS); | 6610 isolate->ReportFailedAccessCheckWrapper(object, v8::ACCESS_HAS); |
| 6620 RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object); | 6611 RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object); |
| 6621 return isolate->factory()->undefined_value(); | 6612 return isolate->factory()->undefined_value(); |
| 6622 } | 6613 } |
| 6623 | 6614 |
| 6624 // Make the lookup and include prototypes. | 6615 // Make the lookup and include prototypes. |
| 6625 uint32_t index = 0; | 6616 uint32_t index = 0; |
| 6626 if (name->AsArrayIndex(&index)) { | 6617 if (name->AsArrayIndex(&index)) { |
| 6627 for (Handle<Object> obj = object; | 6618 for (Handle<Object> obj = object; |
| 6628 !obj->IsNull(); | 6619 !obj->IsNull(); |
| 6629 obj = handle(JSReceiver::cast(*obj)->GetPrototype(), isolate)) { | 6620 obj = handle(JSReceiver::cast(*obj)->GetPrototype(), isolate)) { |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6663 } | 6654 } |
| 6664 | 6655 |
| 6665 | 6656 |
| 6666 Object* JSObject::SlowReverseLookup(Object* value) { | 6657 Object* JSObject::SlowReverseLookup(Object* value) { |
| 6667 if (HasFastProperties()) { | 6658 if (HasFastProperties()) { |
| 6668 int number_of_own_descriptors = map()->NumberOfOwnDescriptors(); | 6659 int number_of_own_descriptors = map()->NumberOfOwnDescriptors(); |
| 6669 DescriptorArray* descs = map()->instance_descriptors(); | 6660 DescriptorArray* descs = map()->instance_descriptors(); |
| 6670 for (int i = 0; i < number_of_own_descriptors; i++) { | 6661 for (int i = 0; i < number_of_own_descriptors; i++) { |
| 6671 if (descs->GetType(i) == FIELD) { | 6662 if (descs->GetType(i) == FIELD) { |
| 6672 Object* property = RawFastPropertyAt(descs->GetFieldIndex(i)); | 6663 Object* property = RawFastPropertyAt(descs->GetFieldIndex(i)); |
| 6673 if (FLAG_track_double_fields && | 6664 if (descs->GetDetails(i).representation().IsDouble()) { |
| 6674 descs->GetDetails(i).representation().IsDouble()) { | |
| 6675 ASSERT(property->IsHeapNumber()); | 6665 ASSERT(property->IsHeapNumber()); |
| 6676 if (value->IsNumber() && property->Number() == value->Number()) { | 6666 if (value->IsNumber() && property->Number() == value->Number()) { |
| 6677 return descs->GetKey(i); | 6667 return descs->GetKey(i); |
| 6678 } | 6668 } |
| 6679 } else if (property == value) { | 6669 } else if (property == value) { |
| 6680 return descs->GetKey(i); | 6670 return descs->GetKey(i); |
| 6681 } | 6671 } |
| 6682 } else if (descs->GetType(i) == CONSTANT) { | 6672 } else if (descs->GetType(i) == CONSTANT) { |
| 6683 if (descs->GetConstant(i) == value) { | 6673 if (descs->GetConstant(i) == value) { |
| 6684 return descs->GetKey(i); | 6674 return descs->GetKey(i); |
| (...skipping 1550 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8235 } | 8225 } |
| 8236 return true; | 8226 return true; |
| 8237 } | 8227 } |
| 8238 #endif | 8228 #endif |
| 8239 | 8229 |
| 8240 | 8230 |
| 8241 static bool IsIdentifier(UnicodeCache* cache, Name* name) { | 8231 static bool IsIdentifier(UnicodeCache* cache, Name* name) { |
| 8242 // Checks whether the buffer contains an identifier (no escape). | 8232 // Checks whether the buffer contains an identifier (no escape). |
| 8243 if (!name->IsString()) return false; | 8233 if (!name->IsString()) return false; |
| 8244 String* string = String::cast(name); | 8234 String* string = String::cast(name); |
| 8245 if (string->length() == 0) return false; | 8235 if (string->length() == 0) return true; |
| 8246 ConsStringIteratorOp op; | 8236 ConsStringIteratorOp op; |
| 8247 StringCharacterStream stream(string, &op); | 8237 StringCharacterStream stream(string, &op); |
| 8248 if (!cache->IsIdentifierStart(stream.GetNext())) { | 8238 if (!cache->IsIdentifierStart(stream.GetNext())) { |
| 8249 return false; | 8239 return false; |
| 8250 } | 8240 } |
| 8251 while (stream.HasMore()) { | 8241 while (stream.HasMore()) { |
| 8252 if (!cache->IsIdentifierPart(stream.GetNext())) { | 8242 if (!cache->IsIdentifierPart(stream.GetNext())) { |
| 8253 return false; | 8243 return false; |
| 8254 } | 8244 } |
| 8255 } | 8245 } |
| 8256 return true; | 8246 return true; |
| 8257 } | 8247 } |
| 8258 | 8248 |
| 8259 | 8249 |
| 8260 bool Name::IsCacheable(Isolate* isolate) { | 8250 bool Name::IsCacheable(Isolate* isolate) { |
| 8261 return IsSymbol() || | 8251 return IsSymbol() || IsIdentifier(isolate->unicode_cache(), this); |
| 8262 IsIdentifier(isolate->unicode_cache(), this) || | |
| 8263 this == isolate->heap()->hidden_string(); | |
| 8264 } | 8252 } |
| 8265 | 8253 |
| 8266 | 8254 |
| 8267 bool String::LooksValid() { | 8255 bool String::LooksValid() { |
| 8268 if (!GetIsolate()->heap()->Contains(this)) return false; | 8256 if (!GetIsolate()->heap()->Contains(this)) return false; |
| 8269 return true; | 8257 return true; |
| 8270 } | 8258 } |
| 8271 | 8259 |
| 8272 | 8260 |
| 8273 String::FlatContent String::GetFlatContent() { | 8261 String::FlatContent String::GetFlatContent() { |
| (...skipping 1185 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9459 | 9447 |
| 9460 bool Map::EquivalentToForNormalization(Map* other, | 9448 bool Map::EquivalentToForNormalization(Map* other, |
| 9461 PropertyNormalizationMode mode) { | 9449 PropertyNormalizationMode mode) { |
| 9462 int properties = mode == CLEAR_INOBJECT_PROPERTIES | 9450 int properties = mode == CLEAR_INOBJECT_PROPERTIES |
| 9463 ? 0 : other->inobject_properties(); | 9451 ? 0 : other->inobject_properties(); |
| 9464 return CheckEquivalent(this, other) && inobject_properties() == properties; | 9452 return CheckEquivalent(this, other) && inobject_properties() == properties; |
| 9465 } | 9453 } |
| 9466 | 9454 |
| 9467 | 9455 |
| 9468 void ConstantPoolArray::ConstantPoolIterateBody(ObjectVisitor* v) { | 9456 void ConstantPoolArray::ConstantPoolIterateBody(ObjectVisitor* v) { |
| 9469 if (count_of_ptr_entries() > 0) { | 9457 for (int i = 0; i < count_of_code_ptr_entries(); i++) { |
| 9470 int first_ptr_offset = OffsetOfElementAt(first_ptr_index()); | 9458 int index = first_code_ptr_index() + i; |
| 9471 int last_ptr_offset = | 9459 v->VisitCodeEntry(reinterpret_cast<Address>(RawFieldOfElementAt(index))); |
| 9472 OffsetOfElementAt(first_ptr_index() + count_of_ptr_entries() - 1); | 9460 } |
| 9473 v->VisitPointers( | 9461 for (int i = 0; i < count_of_heap_ptr_entries(); i++) { |
| 9474 HeapObject::RawField(this, first_ptr_offset), | 9462 int index = first_heap_ptr_index() + i; |
| 9475 HeapObject::RawField(this, last_ptr_offset)); | 9463 v->VisitPointer(RawFieldOfElementAt(index)); |
| 9476 } | 9464 } |
| 9477 } | 9465 } |
| 9478 | 9466 |
| 9479 | 9467 |
| 9480 void JSFunction::JSFunctionIterateBody(int object_size, ObjectVisitor* v) { | 9468 void JSFunction::JSFunctionIterateBody(int object_size, ObjectVisitor* v) { |
| 9481 // Iterate over all fields in the body but take care in dealing with | 9469 // Iterate over all fields in the body but take care in dealing with |
| 9482 // the code entry. | 9470 // the code entry. |
| 9483 IteratePointers(v, kPropertiesOffset, kCodeEntryOffset); | 9471 IteratePointers(v, kPropertiesOffset, kCodeEntryOffset); |
| 9484 v->VisitCodeEntry(this->address() + kCodeEntryOffset); | 9472 v->VisitCodeEntry(this->address() + kCodeEntryOffset); |
| 9485 IteratePointers(v, kCodeEntryOffset + kPointerSize, object_size); | 9473 IteratePointers(v, kCodeEntryOffset + kPointerSize, object_size); |
| (...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9633 | 9621 |
| 9634 ASSERT(code_map->get(kNextMapIndex)->IsUndefined()); | 9622 ASSERT(code_map->get(kNextMapIndex)->IsUndefined()); |
| 9635 set_optimized_code_map(Smi::FromInt(0)); | 9623 set_optimized_code_map(Smi::FromInt(0)); |
| 9636 } | 9624 } |
| 9637 | 9625 |
| 9638 | 9626 |
| 9639 void SharedFunctionInfo::EvictFromOptimizedCodeMap(Code* optimized_code, | 9627 void SharedFunctionInfo::EvictFromOptimizedCodeMap(Code* optimized_code, |
| 9640 const char* reason) { | 9628 const char* reason) { |
| 9641 if (optimized_code_map()->IsSmi()) return; | 9629 if (optimized_code_map()->IsSmi()) return; |
| 9642 | 9630 |
| 9643 int i; | |
| 9644 bool removed_entry = false; | |
| 9645 FixedArray* code_map = FixedArray::cast(optimized_code_map()); | 9631 FixedArray* code_map = FixedArray::cast(optimized_code_map()); |
| 9646 for (i = kEntriesStart; i < code_map->length(); i += kEntryLength) { | 9632 int dst = kEntriesStart; |
| 9647 ASSERT(code_map->get(i)->IsNativeContext()); | 9633 int length = code_map->length(); |
| 9648 if (Code::cast(code_map->get(i + 1)) == optimized_code) { | 9634 for (int src = kEntriesStart; src < length; src += kEntryLength) { |
| 9635 ASSERT(code_map->get(src)->IsNativeContext()); |
| 9636 if (Code::cast(code_map->get(src + kCachedCodeOffset)) == optimized_code) { |
| 9637 // Evict the src entry by not copying it to the dst entry. |
| 9649 if (FLAG_trace_opt) { | 9638 if (FLAG_trace_opt) { |
| 9650 PrintF("[evicting entry from optimizing code map (%s) for ", reason); | 9639 PrintF("[evicting entry from optimizing code map (%s) for ", reason); |
| 9651 ShortPrint(); | 9640 ShortPrint(); |
| 9652 PrintF("]\n"); | 9641 BailoutId osr(Smi::cast(code_map->get(src + kOsrAstIdOffset))->value()); |
| 9642 if (osr.IsNone()) { |
| 9643 PrintF("]\n"); |
| 9644 } else { |
| 9645 PrintF(" (osr ast id %d)]\n", osr.ToInt()); |
| 9646 } |
| 9653 } | 9647 } |
| 9654 removed_entry = true; | 9648 } else { |
| 9655 break; | 9649 // Keep the src entry by copying it to the dst entry. |
| 9650 if (dst != src) { |
| 9651 code_map->set(dst + kContextOffset, |
| 9652 code_map->get(src + kContextOffset)); |
| 9653 code_map->set(dst + kCachedCodeOffset, |
| 9654 code_map->get(src + kCachedCodeOffset)); |
| 9655 code_map->set(dst + kLiteralsOffset, |
| 9656 code_map->get(src + kLiteralsOffset)); |
| 9657 code_map->set(dst + kOsrAstIdOffset, |
| 9658 code_map->get(src + kOsrAstIdOffset)); |
| 9659 } |
| 9660 dst += kEntryLength; |
| 9656 } | 9661 } |
| 9657 } | 9662 } |
| 9658 while (i < (code_map->length() - kEntryLength)) { | 9663 if (dst != length) { |
| 9659 code_map->set(i + kContextOffset, | |
| 9660 code_map->get(i + kContextOffset + kEntryLength)); | |
| 9661 code_map->set(i + kCachedCodeOffset, | |
| 9662 code_map->get(i + kCachedCodeOffset + kEntryLength)); | |
| 9663 code_map->set(i + kLiteralsOffset, | |
| 9664 code_map->get(i + kLiteralsOffset + kEntryLength)); | |
| 9665 code_map->set(i + kOsrAstIdOffset, | |
| 9666 code_map->get(i + kOsrAstIdOffset + kEntryLength)); | |
| 9667 i += kEntryLength; | |
| 9668 } | |
| 9669 if (removed_entry) { | |
| 9670 // Always trim even when array is cleared because of heap verifier. | 9664 // Always trim even when array is cleared because of heap verifier. |
| 9671 RightTrimFixedArray<FROM_MUTATOR>(GetHeap(), code_map, kEntryLength); | 9665 RightTrimFixedArray<FROM_MUTATOR>(GetHeap(), code_map, length - dst); |
| 9672 if (code_map->length() == kEntriesStart) { | 9666 if (code_map->length() == kEntriesStart) ClearOptimizedCodeMap(); |
| 9673 ClearOptimizedCodeMap(); | |
| 9674 } | |
| 9675 } | 9667 } |
| 9676 } | 9668 } |
| 9677 | 9669 |
| 9678 | 9670 |
| 9679 void SharedFunctionInfo::TrimOptimizedCodeMap(int shrink_by) { | 9671 void SharedFunctionInfo::TrimOptimizedCodeMap(int shrink_by) { |
| 9680 FixedArray* code_map = FixedArray::cast(optimized_code_map()); | 9672 FixedArray* code_map = FixedArray::cast(optimized_code_map()); |
| 9681 ASSERT(shrink_by % kEntryLength == 0); | 9673 ASSERT(shrink_by % kEntryLength == 0); |
| 9682 ASSERT(shrink_by <= code_map->length() - kEntriesStart); | 9674 ASSERT(shrink_by <= code_map->length() - kEntriesStart); |
| 9683 // Always trim even when array is cleared because of heap verifier. | 9675 // Always trim even when array is cleared because of heap verifier. |
| 9684 RightTrimFixedArray<FROM_GC>(GetHeap(), code_map, shrink_by); | 9676 RightTrimFixedArray<FROM_GC>(GetHeap(), code_map, shrink_by); |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9792 // If the value is not a JSReceiver, store the value in the map's | 9784 // If the value is not a JSReceiver, store the value in the map's |
| 9793 // constructor field so it can be accessed. Also, set the prototype | 9785 // constructor field so it can be accessed. Also, set the prototype |
| 9794 // used for constructing objects to the original object prototype. | 9786 // used for constructing objects to the original object prototype. |
| 9795 // See ECMA-262 13.2.2. | 9787 // See ECMA-262 13.2.2. |
| 9796 if (!value->IsJSReceiver()) { | 9788 if (!value->IsJSReceiver()) { |
| 9797 // Copy the map so this does not affect unrelated functions. | 9789 // Copy the map so this does not affect unrelated functions. |
| 9798 // Remove map transitions because they point to maps with a | 9790 // Remove map transitions because they point to maps with a |
| 9799 // different prototype. | 9791 // different prototype. |
| 9800 Handle<Map> new_map = Map::Copy(handle(function->map())); | 9792 Handle<Map> new_map = Map::Copy(handle(function->map())); |
| 9801 | 9793 |
| 9802 function->set_map(*new_map); | 9794 JSObject::MigrateToMap(function, new_map); |
| 9803 new_map->set_constructor(*value); | 9795 new_map->set_constructor(*value); |
| 9804 new_map->set_non_instance_prototype(true); | 9796 new_map->set_non_instance_prototype(true); |
| 9805 Isolate* isolate = new_map->GetIsolate(); | 9797 Isolate* isolate = new_map->GetIsolate(); |
| 9806 construct_prototype = handle( | 9798 construct_prototype = handle( |
| 9807 isolate->context()->native_context()->initial_object_prototype(), | 9799 isolate->context()->native_context()->initial_object_prototype(), |
| 9808 isolate); | 9800 isolate); |
| 9809 } else { | 9801 } else { |
| 9810 function->map()->set_non_instance_prototype(false); | 9802 function->map()->set_non_instance_prototype(false); |
| 9811 } | 9803 } |
| 9812 | 9804 |
| 9813 return SetInstancePrototype(function, construct_prototype); | 9805 return SetInstancePrototype(function, construct_prototype); |
| 9814 } | 9806 } |
| 9815 | 9807 |
| 9816 | 9808 |
| 9817 void JSFunction::RemovePrototype() { | 9809 void JSFunction::RemovePrototype() { |
| 9818 Context* native_context = context()->native_context(); | 9810 Context* native_context = context()->native_context(); |
| 9819 Map* no_prototype_map = shared()->is_classic_mode() | 9811 Map* no_prototype_map = shared()->strict_mode() == SLOPPY |
| 9820 ? native_context->function_without_prototype_map() | 9812 ? native_context->sloppy_function_without_prototype_map() |
| 9821 : native_context->strict_mode_function_without_prototype_map(); | 9813 : native_context->strict_function_without_prototype_map(); |
| 9822 | 9814 |
| 9823 if (map() == no_prototype_map) return; | 9815 if (map() == no_prototype_map) return; |
| 9824 | 9816 |
| 9825 ASSERT(map() == (shared()->is_classic_mode() | 9817 ASSERT(map() == (shared()->strict_mode() == SLOPPY |
| 9826 ? native_context->function_map() | 9818 ? native_context->sloppy_function_map() |
| 9827 : native_context->strict_mode_function_map())); | 9819 : native_context->strict_function_map())); |
| 9828 | 9820 |
| 9829 set_map(no_prototype_map); | 9821 set_map(no_prototype_map); |
| 9830 set_prototype_or_initial_map(no_prototype_map->GetHeap()->the_hole_value()); | 9822 set_prototype_or_initial_map(no_prototype_map->GetHeap()->the_hole_value()); |
| 9831 } | 9823 } |
| 9832 | 9824 |
| 9833 | 9825 |
| 9834 void JSFunction::EnsureHasInitialMap(Handle<JSFunction> function) { | 9826 void JSFunction::EnsureHasInitialMap(Handle<JSFunction> function) { |
| 9835 if (function->has_initial_map()) return; | 9827 if (function->has_initial_map()) return; |
| 9836 Isolate* isolate = function->GetIsolate(); | 9828 Isolate* isolate = function->GetIsolate(); |
| 9837 | 9829 |
| (...skipping 797 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10635 | 10627 |
| 10636 void Code::ClearInlineCaches(Code::Kind* kind) { | 10628 void Code::ClearInlineCaches(Code::Kind* kind) { |
| 10637 int mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET) | | 10629 int mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET) | |
| 10638 RelocInfo::ModeMask(RelocInfo::CONSTRUCT_CALL) | | 10630 RelocInfo::ModeMask(RelocInfo::CONSTRUCT_CALL) | |
| 10639 RelocInfo::ModeMask(RelocInfo::CODE_TARGET_WITH_ID); | 10631 RelocInfo::ModeMask(RelocInfo::CODE_TARGET_WITH_ID); |
| 10640 for (RelocIterator it(this, mask); !it.done(); it.next()) { | 10632 for (RelocIterator it(this, mask); !it.done(); it.next()) { |
| 10641 RelocInfo* info = it.rinfo(); | 10633 RelocInfo* info = it.rinfo(); |
| 10642 Code* target(Code::GetCodeFromTargetAddress(info->target_address())); | 10634 Code* target(Code::GetCodeFromTargetAddress(info->target_address())); |
| 10643 if (target->is_inline_cache_stub()) { | 10635 if (target->is_inline_cache_stub()) { |
| 10644 if (kind == NULL || *kind == target->kind()) { | 10636 if (kind == NULL || *kind == target->kind()) { |
| 10645 IC::Clear(this->GetIsolate(), info->pc()); | 10637 IC::Clear(this->GetIsolate(), info->pc(), |
| 10638 info->host()->constant_pool()); |
| 10646 } | 10639 } |
| 10647 } | 10640 } |
| 10648 } | 10641 } |
| 10649 } | 10642 } |
| 10650 | 10643 |
| 10651 | 10644 |
| 10652 void Code::ClearTypeFeedbackInfo(Heap* heap) { | 10645 void SharedFunctionInfo::ClearTypeFeedbackInfo(Heap* heap) { |
| 10653 if (kind() != FUNCTION) return; | 10646 FixedArray* vector = feedback_vector(); |
| 10654 Object* raw_info = type_feedback_info(); | 10647 for (int i = 0; i < vector->length(); i++) { |
| 10655 if (raw_info->IsTypeFeedbackInfo()) { | 10648 Object* obj = vector->get(i); |
| 10656 FixedArray* feedback_vector = | 10649 if (!obj->IsAllocationSite()) { |
| 10657 TypeFeedbackInfo::cast(raw_info)->feedback_vector(); | 10650 // The assert verifies we can skip the write barrier. |
| 10658 for (int i = 0; i < feedback_vector->length(); i++) { | 10651 ASSERT(heap->uninitialized_symbol() == |
| 10659 Object* obj = feedback_vector->get(i); | 10652 TypeFeedbackInfo::RawUninitializedSentinel(heap)); |
| 10660 if (!obj->IsAllocationSite()) { | 10653 vector->set(i, TypeFeedbackInfo::RawUninitializedSentinel(heap), |
| 10661 // TODO(mvstanton): Can't I avoid a write barrier for this sentinel? | 10654 SKIP_WRITE_BARRIER); |
| 10662 feedback_vector->set(i, | |
| 10663 TypeFeedbackInfo::RawUninitializedSentinel(heap)); | |
| 10664 } | |
| 10665 } | 10655 } |
| 10666 } | 10656 } |
| 10667 } | 10657 } |
| 10668 | 10658 |
| 10669 | 10659 |
| 10670 BailoutId Code::TranslatePcOffsetToAstId(uint32_t pc_offset) { | 10660 BailoutId Code::TranslatePcOffsetToAstId(uint32_t pc_offset) { |
| 10671 DisallowHeapAllocation no_gc; | 10661 DisallowHeapAllocation no_gc; |
| 10672 ASSERT(kind() == FUNCTION); | 10662 ASSERT(kind() == FUNCTION); |
| 10673 BackEdgeTable back_edges(this, &no_gc); | 10663 BackEdgeTable back_edges(this, &no_gc); |
| 10674 for (uint32_t i = 0; i < back_edges.length(); i++) { | 10664 for (uint32_t i = 0; i < back_edges.length(); i++) { |
| (...skipping 404 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 11079 return NULL; | 11069 return NULL; |
| 11080 } | 11070 } |
| 11081 | 11071 |
| 11082 | 11072 |
| 11083 void Code::PrintExtraICState(FILE* out, Kind kind, ExtraICState extra) { | 11073 void Code::PrintExtraICState(FILE* out, Kind kind, ExtraICState extra) { |
| 11084 PrintF(out, "extra_ic_state = "); | 11074 PrintF(out, "extra_ic_state = "); |
| 11085 const char* name = NULL; | 11075 const char* name = NULL; |
| 11086 switch (kind) { | 11076 switch (kind) { |
| 11087 case STORE_IC: | 11077 case STORE_IC: |
| 11088 case KEYED_STORE_IC: | 11078 case KEYED_STORE_IC: |
| 11089 if (extra == kStrictMode) { | 11079 if (extra == STRICT) name = "STRICT"; |
| 11090 name = "STRICT"; | |
| 11091 } | |
| 11092 break; | 11080 break; |
| 11093 default: | 11081 default: |
| 11094 break; | 11082 break; |
| 11095 } | 11083 } |
| 11096 if (name != NULL) { | 11084 if (name != NULL) { |
| 11097 PrintF(out, "%s\n", name); | 11085 PrintF(out, "%s\n", name); |
| 11098 } else { | 11086 } else { |
| 11099 PrintF(out, "%d\n", extra); | 11087 PrintF(out, "%d\n", extra); |
| 11100 } | 11088 } |
| 11101 } | 11089 } |
| (...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 11248 } else { | 11236 } else { |
| 11249 new_elements_kind = FAST_ELEMENTS; | 11237 new_elements_kind = FAST_ELEMENTS; |
| 11250 } | 11238 } |
| 11251 } | 11239 } |
| 11252 FixedArrayBase* old_elements = elements(); | 11240 FixedArrayBase* old_elements = elements(); |
| 11253 ElementsAccessor* accessor = ElementsAccessor::ForKind(new_elements_kind); | 11241 ElementsAccessor* accessor = ElementsAccessor::ForKind(new_elements_kind); |
| 11254 MaybeObject* maybe_obj = | 11242 MaybeObject* maybe_obj = |
| 11255 accessor->CopyElements(this, new_elements, elements_kind); | 11243 accessor->CopyElements(this, new_elements, elements_kind); |
| 11256 if (maybe_obj->IsFailure()) return maybe_obj; | 11244 if (maybe_obj->IsFailure()) return maybe_obj; |
| 11257 | 11245 |
| 11258 if (elements_kind != NON_STRICT_ARGUMENTS_ELEMENTS) { | 11246 if (elements_kind != SLOPPY_ARGUMENTS_ELEMENTS) { |
| 11259 Map* new_map = map(); | 11247 Map* new_map = map(); |
| 11260 if (new_elements_kind != elements_kind) { | 11248 if (new_elements_kind != elements_kind) { |
| 11261 MaybeObject* maybe = | 11249 MaybeObject* maybe = |
| 11262 GetElementsTransitionMap(GetIsolate(), new_elements_kind); | 11250 GetElementsTransitionMap(GetIsolate(), new_elements_kind); |
| 11263 if (!maybe->To(&new_map)) return maybe; | 11251 if (!maybe->To(&new_map)) return maybe; |
| 11264 } | 11252 } |
| 11265 ValidateElements(); | 11253 ValidateElements(); |
| 11266 set_map_and_elements(new_map, new_elements); | 11254 set_map_and_elements(new_map, new_elements); |
| 11267 | 11255 |
| 11268 // Transition through the allocation site as well if present. | 11256 // Transition through the allocation site as well if present. |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 11320 GetElementsTransitionMap(heap->isolate(), new_elements_kind); | 11308 GetElementsTransitionMap(heap->isolate(), new_elements_kind); |
| 11321 if (!maybe_obj->To(&new_map)) return maybe_obj; | 11309 if (!maybe_obj->To(&new_map)) return maybe_obj; |
| 11322 } | 11310 } |
| 11323 | 11311 |
| 11324 FixedArrayBase* old_elements = elements(); | 11312 FixedArrayBase* old_elements = elements(); |
| 11325 ElementsAccessor* accessor = ElementsAccessor::ForKind(FAST_DOUBLE_ELEMENTS); | 11313 ElementsAccessor* accessor = ElementsAccessor::ForKind(FAST_DOUBLE_ELEMENTS); |
| 11326 { MaybeObject* maybe_obj = | 11314 { MaybeObject* maybe_obj = |
| 11327 accessor->CopyElements(this, elems, elements_kind); | 11315 accessor->CopyElements(this, elems, elements_kind); |
| 11328 if (maybe_obj->IsFailure()) return maybe_obj; | 11316 if (maybe_obj->IsFailure()) return maybe_obj; |
| 11329 } | 11317 } |
| 11330 if (elements_kind != NON_STRICT_ARGUMENTS_ELEMENTS) { | 11318 if (elements_kind != SLOPPY_ARGUMENTS_ELEMENTS) { |
| 11331 ValidateElements(); | 11319 ValidateElements(); |
| 11332 set_map_and_elements(new_map, elems); | 11320 set_map_and_elements(new_map, elems); |
| 11333 } else { | 11321 } else { |
| 11334 FixedArray* parameter_map = FixedArray::cast(old_elements); | 11322 FixedArray* parameter_map = FixedArray::cast(old_elements); |
| 11335 parameter_map->set(1, elems); | 11323 parameter_map->set(1, elems); |
| 11336 } | 11324 } |
| 11337 | 11325 |
| 11338 if (FLAG_trace_elements_transitions) { | 11326 if (FLAG_trace_elements_transitions) { |
| 11339 PrintElementsTransition(stdout, elements_kind, old_elements, | 11327 PrintElementsTransition(stdout, elements_kind, old_elements, |
| 11340 GetElementsKind(), elems); | 11328 GetElementsKind(), elems); |
| (...skipping 21 matching lines...) Expand all Loading... |
| 11362 | 11350 |
| 11363 | 11351 |
| 11364 // Returns false if the passed-in index is marked non-configurable, | 11352 // Returns false if the passed-in index is marked non-configurable, |
| 11365 // which will cause the ES5 truncation operation to halt, and thus | 11353 // which will cause the ES5 truncation operation to halt, and thus |
| 11366 // no further old values need be collected. | 11354 // no further old values need be collected. |
| 11367 static bool GetOldValue(Isolate* isolate, | 11355 static bool GetOldValue(Isolate* isolate, |
| 11368 Handle<JSObject> object, | 11356 Handle<JSObject> object, |
| 11369 uint32_t index, | 11357 uint32_t index, |
| 11370 List<Handle<Object> >* old_values, | 11358 List<Handle<Object> >* old_values, |
| 11371 List<uint32_t>* indices) { | 11359 List<uint32_t>* indices) { |
| 11372 PropertyAttributes attributes = object->GetLocalElementAttribute(index); | 11360 PropertyAttributes attributes = |
| 11361 JSReceiver::GetLocalElementAttribute(object, index); |
| 11373 ASSERT(attributes != ABSENT); | 11362 ASSERT(attributes != ABSENT); |
| 11374 if (attributes == DONT_DELETE) return false; | 11363 if (attributes == DONT_DELETE) return false; |
| 11375 old_values->Add(object->GetLocalElementAccessorPair(index) == NULL | 11364 old_values->Add(object->GetLocalElementAccessorPair(index) == NULL |
| 11376 ? Object::GetElement(isolate, object, index) | 11365 ? Object::GetElement(isolate, object, index) |
| 11377 : Handle<Object>::cast(isolate->factory()->the_hole_value())); | 11366 : Handle<Object>::cast(isolate->factory()->the_hole_value())); |
| 11378 indices->Add(index); | 11367 indices->Add(index); |
| 11379 return true; | 11368 return true; |
| 11380 } | 11369 } |
| 11381 | 11370 |
| 11382 static void EnqueueSpliceRecord(Handle<JSArray> object, | 11371 static void EnqueueSpliceRecord(Handle<JSArray> object, |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 11425 Handle<JSFunction>(isolate->observers_end_perform_splice()), | 11414 Handle<JSFunction>(isolate->observers_end_perform_splice()), |
| 11426 isolate->factory()->undefined_value(), ARRAY_SIZE(args), args, | 11415 isolate->factory()->undefined_value(), ARRAY_SIZE(args), args, |
| 11427 &threw); | 11416 &threw); |
| 11428 ASSERT(!threw); | 11417 ASSERT(!threw); |
| 11429 } | 11418 } |
| 11430 | 11419 |
| 11431 | 11420 |
| 11432 MaybeObject* JSArray::SetElementsLength(Object* len) { | 11421 MaybeObject* JSArray::SetElementsLength(Object* len) { |
| 11433 // We should never end in here with a pixel or external array. | 11422 // We should never end in here with a pixel or external array. |
| 11434 ASSERT(AllowsSetElementsLength()); | 11423 ASSERT(AllowsSetElementsLength()); |
| 11435 if (!(FLAG_harmony_observation && map()->is_observed())) | 11424 if (!map()->is_observed()) |
| 11436 return GetElementsAccessor()->SetLength(this, len); | 11425 return GetElementsAccessor()->SetLength(this, len); |
| 11437 | 11426 |
| 11438 Isolate* isolate = GetIsolate(); | 11427 Isolate* isolate = GetIsolate(); |
| 11439 HandleScope scope(isolate); | 11428 HandleScope scope(isolate); |
| 11440 Handle<JSArray> self(this); | 11429 Handle<JSArray> self(this); |
| 11441 List<uint32_t> indices; | 11430 List<uint32_t> indices; |
| 11442 List<Handle<Object> > old_values; | 11431 List<Handle<Object> > old_values; |
| 11443 Handle<Object> old_length_handle(self->length(), isolate); | 11432 Handle<Object> old_length_handle(self->length(), isolate); |
| 11444 Handle<Object> new_length_handle(len, isolate); | 11433 Handle<Object> new_length_handle(len, isolate); |
| 11445 uint32_t old_length = 0; | 11434 uint32_t old_length = 0; |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 11491 | 11480 |
| 11492 EndPerformSplice(self); | 11481 EndPerformSplice(self); |
| 11493 | 11482 |
| 11494 uint32_t index = Min(old_length, new_length); | 11483 uint32_t index = Min(old_length, new_length); |
| 11495 uint32_t add_count = new_length > old_length ? new_length - old_length : 0; | 11484 uint32_t add_count = new_length > old_length ? new_length - old_length : 0; |
| 11496 uint32_t delete_count = new_length < old_length ? old_length - new_length : 0; | 11485 uint32_t delete_count = new_length < old_length ? old_length - new_length : 0; |
| 11497 Handle<JSArray> deleted = isolate->factory()->NewJSArray(0); | 11486 Handle<JSArray> deleted = isolate->factory()->NewJSArray(0); |
| 11498 if (delete_count > 0) { | 11487 if (delete_count > 0) { |
| 11499 for (int i = indices.length() - 1; i >= 0; i--) { | 11488 for (int i = indices.length() - 1; i >= 0; i--) { |
| 11500 JSObject::SetElement(deleted, indices[i] - index, old_values[i], NONE, | 11489 JSObject::SetElement(deleted, indices[i] - index, old_values[i], NONE, |
| 11501 kNonStrictMode); | 11490 SLOPPY); |
| 11502 } | 11491 } |
| 11503 | 11492 |
| 11504 SetProperty(deleted, isolate->factory()->length_string(), | 11493 SetProperty(deleted, isolate->factory()->length_string(), |
| 11505 isolate->factory()->NewNumberFromUint(delete_count), | 11494 isolate->factory()->NewNumberFromUint(delete_count), |
| 11506 NONE, kNonStrictMode); | 11495 NONE, SLOPPY); |
| 11507 } | 11496 } |
| 11508 | 11497 |
| 11509 EnqueueSpliceRecord(self, index, deleted, add_count); | 11498 EnqueueSpliceRecord(self, index, deleted, add_count); |
| 11510 | 11499 |
| 11511 return *hresult; | 11500 return *hresult; |
| 11512 } | 11501 } |
| 11513 | 11502 |
| 11514 | 11503 |
| 11515 Handle<Map> Map::GetPrototypeTransition(Handle<Map> map, | 11504 Handle<Map> Map::GetPrototypeTransition(Handle<Map> map, |
| 11516 Handle<Object> prototype) { | 11505 Handle<Object> prototype) { |
| (...skipping 352 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 11869 JSObject::OptimizeAsPrototype(Handle<JSObject>::cast(value)); | 11858 JSObject::OptimizeAsPrototype(Handle<JSObject>::cast(value)); |
| 11870 } | 11859 } |
| 11871 | 11860 |
| 11872 Handle<Map> new_map = Map::GetPrototypeTransition(map, value); | 11861 Handle<Map> new_map = Map::GetPrototypeTransition(map, value); |
| 11873 if (new_map.is_null()) { | 11862 if (new_map.is_null()) { |
| 11874 new_map = Map::Copy(map); | 11863 new_map = Map::Copy(map); |
| 11875 Map::PutPrototypeTransition(map, value, new_map); | 11864 Map::PutPrototypeTransition(map, value, new_map); |
| 11876 new_map->set_prototype(*value); | 11865 new_map->set_prototype(*value); |
| 11877 } | 11866 } |
| 11878 ASSERT(new_map->prototype() == *value); | 11867 ASSERT(new_map->prototype() == *value); |
| 11879 real_receiver->set_map(*new_map); | 11868 JSObject::MigrateToMap(real_receiver, new_map); |
| 11880 | 11869 |
| 11881 if (!dictionary_elements_in_chain && | 11870 if (!dictionary_elements_in_chain && |
| 11882 new_map->DictionaryElementsInPrototypeChainOnly()) { | 11871 new_map->DictionaryElementsInPrototypeChainOnly()) { |
| 11883 // If the prototype chain didn't previously have element callbacks, then | 11872 // If the prototype chain didn't previously have element callbacks, then |
| 11884 // KeyedStoreICs need to be cleared to ensure any that involve this | 11873 // KeyedStoreICs need to be cleared to ensure any that involve this |
| 11885 // map go generic. | 11874 // map go generic. |
| 11886 object->GetHeap()->ClearAllICsByKind(Code::KEYED_STORE_IC); | 11875 object->GetHeap()->ClearAllICsByKind(Code::KEYED_STORE_IC); |
| 11887 } | 11876 } |
| 11888 | 11877 |
| 11889 heap->ClearInstanceofCache(); | 11878 heap->ClearInstanceofCache(); |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 11935 | 11924 |
| 11936 return GetElementsAccessor()->GetAccessorPair(this, this, index); | 11925 return GetElementsAccessor()->GetAccessorPair(this, this, index); |
| 11937 } | 11926 } |
| 11938 | 11927 |
| 11939 | 11928 |
| 11940 Handle<Object> JSObject::SetElementWithInterceptor( | 11929 Handle<Object> JSObject::SetElementWithInterceptor( |
| 11941 Handle<JSObject> object, | 11930 Handle<JSObject> object, |
| 11942 uint32_t index, | 11931 uint32_t index, |
| 11943 Handle<Object> value, | 11932 Handle<Object> value, |
| 11944 PropertyAttributes attributes, | 11933 PropertyAttributes attributes, |
| 11945 StrictModeFlag strict_mode, | 11934 StrictMode strict_mode, |
| 11946 bool check_prototype, | 11935 bool check_prototype, |
| 11947 SetPropertyMode set_mode) { | 11936 SetPropertyMode set_mode) { |
| 11948 Isolate* isolate = object->GetIsolate(); | 11937 Isolate* isolate = object->GetIsolate(); |
| 11949 | 11938 |
| 11950 // Make sure that the top context does not change when doing | 11939 // Make sure that the top context does not change when doing |
| 11951 // callbacks or interceptor calls. | 11940 // callbacks or interceptor calls. |
| 11952 AssertNoContextChange ncc(isolate); | 11941 AssertNoContextChange ncc(isolate); |
| 11953 | 11942 |
| 11954 Handle<InterceptorInfo> interceptor(object->GetIndexedInterceptor()); | 11943 Handle<InterceptorInfo> interceptor(object->GetIndexedInterceptor()); |
| 11955 if (!interceptor->setter()->IsUndefined()) { | 11944 if (!interceptor->setter()->IsUndefined()) { |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 12023 UNREACHABLE(); | 12012 UNREACHABLE(); |
| 12024 return NULL; | 12013 return NULL; |
| 12025 } | 12014 } |
| 12026 | 12015 |
| 12027 | 12016 |
| 12028 Handle<Object> JSObject::SetElementWithCallback(Handle<JSObject> object, | 12017 Handle<Object> JSObject::SetElementWithCallback(Handle<JSObject> object, |
| 12029 Handle<Object> structure, | 12018 Handle<Object> structure, |
| 12030 uint32_t index, | 12019 uint32_t index, |
| 12031 Handle<Object> value, | 12020 Handle<Object> value, |
| 12032 Handle<JSObject> holder, | 12021 Handle<JSObject> holder, |
| 12033 StrictModeFlag strict_mode) { | 12022 StrictMode strict_mode) { |
| 12034 Isolate* isolate = object->GetIsolate(); | 12023 Isolate* isolate = object->GetIsolate(); |
| 12035 | 12024 |
| 12036 // We should never get here to initialize a const with the hole | 12025 // We should never get here to initialize a const with the hole |
| 12037 // value since a const declaration would conflict with the setter. | 12026 // value since a const declaration would conflict with the setter. |
| 12038 ASSERT(!value->IsTheHole()); | 12027 ASSERT(!value->IsTheHole()); |
| 12039 | 12028 |
| 12040 // To accommodate both the old and the new api we switch on the | 12029 // To accommodate both the old and the new api we switch on the |
| 12041 // data structure used to store the callbacks. Eventually foreign | 12030 // data structure used to store the callbacks. Eventually foreign |
| 12042 // callbacks should be phased out. | 12031 // callbacks should be phased out. |
| 12043 ASSERT(!structure->IsForeign()); | 12032 ASSERT(!structure->IsForeign()); |
| (...skipping 18 matching lines...) Expand all Loading... |
| 12062 return value; | 12051 return value; |
| 12063 } | 12052 } |
| 12064 | 12053 |
| 12065 if (structure->IsAccessorPair()) { | 12054 if (structure->IsAccessorPair()) { |
| 12066 Handle<Object> setter(AccessorPair::cast(*structure)->setter(), isolate); | 12055 Handle<Object> setter(AccessorPair::cast(*structure)->setter(), isolate); |
| 12067 if (setter->IsSpecFunction()) { | 12056 if (setter->IsSpecFunction()) { |
| 12068 // TODO(rossberg): nicer would be to cast to some JSCallable here... | 12057 // TODO(rossberg): nicer would be to cast to some JSCallable here... |
| 12069 return SetPropertyWithDefinedSetter( | 12058 return SetPropertyWithDefinedSetter( |
| 12070 object, Handle<JSReceiver>::cast(setter), value); | 12059 object, Handle<JSReceiver>::cast(setter), value); |
| 12071 } else { | 12060 } else { |
| 12072 if (strict_mode == kNonStrictMode) { | 12061 if (strict_mode == SLOPPY) return value; |
| 12073 return value; | |
| 12074 } | |
| 12075 Handle<Object> key(isolate->factory()->NewNumberFromUint(index)); | 12062 Handle<Object> key(isolate->factory()->NewNumberFromUint(index)); |
| 12076 Handle<Object> args[2] = { key, holder }; | 12063 Handle<Object> args[2] = { key, holder }; |
| 12077 Handle<Object> error = isolate->factory()->NewTypeError( | 12064 Handle<Object> error = isolate->factory()->NewTypeError( |
| 12078 "no_setter_in_callback", HandleVector(args, 2)); | 12065 "no_setter_in_callback", HandleVector(args, 2)); |
| 12079 isolate->Throw(*error); | 12066 isolate->Throw(*error); |
| 12080 return Handle<Object>(); | 12067 return Handle<Object>(); |
| 12081 } | 12068 } |
| 12082 } | 12069 } |
| 12083 | 12070 |
| 12084 // TODO(dcarney): Handle correctly. | 12071 // TODO(dcarney): Handle correctly. |
| 12085 if (structure->IsDeclaredAccessorInfo()) return value; | 12072 if (structure->IsDeclaredAccessorInfo()) return value; |
| 12086 | 12073 |
| 12087 UNREACHABLE(); | 12074 UNREACHABLE(); |
| 12088 return Handle<Object>(); | 12075 return Handle<Object>(); |
| 12089 } | 12076 } |
| 12090 | 12077 |
| 12091 | 12078 |
| 12092 bool JSObject::HasFastArgumentsElements() { | 12079 bool JSObject::HasFastArgumentsElements() { |
| 12093 Heap* heap = GetHeap(); | 12080 Heap* heap = GetHeap(); |
| 12094 if (!elements()->IsFixedArray()) return false; | 12081 if (!elements()->IsFixedArray()) return false; |
| 12095 FixedArray* elements = FixedArray::cast(this->elements()); | 12082 FixedArray* elements = FixedArray::cast(this->elements()); |
| 12096 if (elements->map() != heap->non_strict_arguments_elements_map()) { | 12083 if (elements->map() != heap->sloppy_arguments_elements_map()) { |
| 12097 return false; | 12084 return false; |
| 12098 } | 12085 } |
| 12099 FixedArray* arguments = FixedArray::cast(elements->get(1)); | 12086 FixedArray* arguments = FixedArray::cast(elements->get(1)); |
| 12100 return !arguments->IsDictionary(); | 12087 return !arguments->IsDictionary(); |
| 12101 } | 12088 } |
| 12102 | 12089 |
| 12103 | 12090 |
| 12104 bool JSObject::HasDictionaryArgumentsElements() { | 12091 bool JSObject::HasDictionaryArgumentsElements() { |
| 12105 Heap* heap = GetHeap(); | 12092 Heap* heap = GetHeap(); |
| 12106 if (!elements()->IsFixedArray()) return false; | 12093 if (!elements()->IsFixedArray()) return false; |
| 12107 FixedArray* elements = FixedArray::cast(this->elements()); | 12094 FixedArray* elements = FixedArray::cast(this->elements()); |
| 12108 if (elements->map() != heap->non_strict_arguments_elements_map()) { | 12095 if (elements->map() != heap->sloppy_arguments_elements_map()) { |
| 12109 return false; | 12096 return false; |
| 12110 } | 12097 } |
| 12111 FixedArray* arguments = FixedArray::cast(elements->get(1)); | 12098 FixedArray* arguments = FixedArray::cast(elements->get(1)); |
| 12112 return arguments->IsDictionary(); | 12099 return arguments->IsDictionary(); |
| 12113 } | 12100 } |
| 12114 | 12101 |
| 12115 | 12102 |
| 12116 // Adding n elements in fast case is O(n*n). | 12103 // Adding n elements in fast case is O(n*n). |
| 12117 // Note: revisit design to have dual undefined values to capture absent | 12104 // Note: revisit design to have dual undefined values to capture absent |
| 12118 // elements. | 12105 // elements. |
| 12119 Handle<Object> JSObject::SetFastElement(Handle<JSObject> object, | 12106 Handle<Object> JSObject::SetFastElement(Handle<JSObject> object, |
| 12120 uint32_t index, | 12107 uint32_t index, |
| 12121 Handle<Object> value, | 12108 Handle<Object> value, |
| 12122 StrictModeFlag strict_mode, | 12109 StrictMode strict_mode, |
| 12123 bool check_prototype) { | 12110 bool check_prototype) { |
| 12124 ASSERT(object->HasFastSmiOrObjectElements() || | 12111 ASSERT(object->HasFastSmiOrObjectElements() || |
| 12125 object->HasFastArgumentsElements()); | 12112 object->HasFastArgumentsElements()); |
| 12126 | 12113 |
| 12127 Isolate* isolate = object->GetIsolate(); | 12114 Isolate* isolate = object->GetIsolate(); |
| 12128 | 12115 |
| 12129 // Array optimizations rely on the prototype lookups of Array objects always | 12116 // Array optimizations rely on the prototype lookups of Array objects always |
| 12130 // returning undefined. If there is a store to the initial prototype object, | 12117 // returning undefined. If there is a store to the initial prototype object, |
| 12131 // make sure all of these optimizations are invalidated. | 12118 // make sure all of these optimizations are invalidated. |
| 12132 if (isolate->is_initial_object_prototype(*object) || | 12119 if (isolate->is_initial_object_prototype(*object) || |
| 12133 isolate->is_initial_array_prototype(*object)) { | 12120 isolate->is_initial_array_prototype(*object)) { |
| 12134 object->map()->dependent_code()->DeoptimizeDependentCodeGroup(isolate, | 12121 object->map()->dependent_code()->DeoptimizeDependentCodeGroup(isolate, |
| 12135 DependentCode::kElementsCantBeAddedGroup); | 12122 DependentCode::kElementsCantBeAddedGroup); |
| 12136 } | 12123 } |
| 12137 | 12124 |
| 12138 Handle<FixedArray> backing_store(FixedArray::cast(object->elements())); | 12125 Handle<FixedArray> backing_store(FixedArray::cast(object->elements())); |
| 12139 if (backing_store->map() == | 12126 if (backing_store->map() == |
| 12140 isolate->heap()->non_strict_arguments_elements_map()) { | 12127 isolate->heap()->sloppy_arguments_elements_map()) { |
| 12141 backing_store = handle(FixedArray::cast(backing_store->get(1))); | 12128 backing_store = handle(FixedArray::cast(backing_store->get(1))); |
| 12142 } else { | 12129 } else { |
| 12143 backing_store = EnsureWritableFastElements(object); | 12130 backing_store = EnsureWritableFastElements(object); |
| 12144 } | 12131 } |
| 12145 uint32_t capacity = static_cast<uint32_t>(backing_store->length()); | 12132 uint32_t capacity = static_cast<uint32_t>(backing_store->length()); |
| 12146 | 12133 |
| 12147 if (check_prototype && | 12134 if (check_prototype && |
| 12148 (index >= capacity || backing_store->get(index)->IsTheHole())) { | 12135 (index >= capacity || backing_store->get(index)->IsTheHole())) { |
| 12149 bool found; | 12136 bool found; |
| 12150 Handle<Object> result = SetElementWithCallbackSetterInPrototypes( | 12137 Handle<Object> result = SetElementWithCallbackSetterInPrototypes( |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 12210 return value; | 12197 return value; |
| 12211 } | 12198 } |
| 12212 // Change elements kind from Smi-only to generic FAST if necessary. | 12199 // Change elements kind from Smi-only to generic FAST if necessary. |
| 12213 if (object->HasFastSmiElements() && !value->IsSmi()) { | 12200 if (object->HasFastSmiElements() && !value->IsSmi()) { |
| 12214 ElementsKind kind = object->HasFastHoleyElements() | 12201 ElementsKind kind = object->HasFastHoleyElements() |
| 12215 ? FAST_HOLEY_ELEMENTS | 12202 ? FAST_HOLEY_ELEMENTS |
| 12216 : FAST_ELEMENTS; | 12203 : FAST_ELEMENTS; |
| 12217 | 12204 |
| 12218 UpdateAllocationSite(object, kind); | 12205 UpdateAllocationSite(object, kind); |
| 12219 Handle<Map> new_map = GetElementsTransitionMap(object, kind); | 12206 Handle<Map> new_map = GetElementsTransitionMap(object, kind); |
| 12220 object->set_map(*new_map); | 12207 JSObject::MigrateToMap(object, new_map); |
| 12221 ASSERT(IsFastObjectElementsKind(object->GetElementsKind())); | 12208 ASSERT(IsFastObjectElementsKind(object->GetElementsKind())); |
| 12222 } | 12209 } |
| 12223 // Increase backing store capacity if that's been decided previously. | 12210 // Increase backing store capacity if that's been decided previously. |
| 12224 if (new_capacity != capacity) { | 12211 if (new_capacity != capacity) { |
| 12225 SetFastElementsCapacitySmiMode smi_mode = | 12212 SetFastElementsCapacitySmiMode smi_mode = |
| 12226 value->IsSmi() && object->HasFastSmiElements() | 12213 value->IsSmi() && object->HasFastSmiElements() |
| 12227 ? kAllowSmiElements | 12214 ? kAllowSmiElements |
| 12228 : kDontAllowSmiElements; | 12215 : kDontAllowSmiElements; |
| 12229 Handle<FixedArray> new_elements = | 12216 Handle<FixedArray> new_elements = |
| 12230 SetFastElementsCapacityAndLength(object, new_capacity, array_length, | 12217 SetFastElementsCapacityAndLength(object, new_capacity, array_length, |
| (...skipping 10 matching lines...) Expand all Loading... |
| 12241 Handle<JSArray>::cast(object)->set_length(Smi::FromInt(array_length)); | 12228 Handle<JSArray>::cast(object)->set_length(Smi::FromInt(array_length)); |
| 12242 } | 12229 } |
| 12243 return value; | 12230 return value; |
| 12244 } | 12231 } |
| 12245 | 12232 |
| 12246 | 12233 |
| 12247 Handle<Object> JSObject::SetDictionaryElement(Handle<JSObject> object, | 12234 Handle<Object> JSObject::SetDictionaryElement(Handle<JSObject> object, |
| 12248 uint32_t index, | 12235 uint32_t index, |
| 12249 Handle<Object> value, | 12236 Handle<Object> value, |
| 12250 PropertyAttributes attributes, | 12237 PropertyAttributes attributes, |
| 12251 StrictModeFlag strict_mode, | 12238 StrictMode strict_mode, |
| 12252 bool check_prototype, | 12239 bool check_prototype, |
| 12253 SetPropertyMode set_mode) { | 12240 SetPropertyMode set_mode) { |
| 12254 ASSERT(object->HasDictionaryElements() || | 12241 ASSERT(object->HasDictionaryElements() || |
| 12255 object->HasDictionaryArgumentsElements()); | 12242 object->HasDictionaryArgumentsElements()); |
| 12256 Isolate* isolate = object->GetIsolate(); | 12243 Isolate* isolate = object->GetIsolate(); |
| 12257 | 12244 |
| 12258 // Insert element in the dictionary. | 12245 // Insert element in the dictionary. |
| 12259 Handle<FixedArray> elements(FixedArray::cast(object->elements())); | 12246 Handle<FixedArray> elements(FixedArray::cast(object->elements())); |
| 12260 bool is_arguments = | 12247 bool is_arguments = |
| 12261 (elements->map() == isolate->heap()->non_strict_arguments_elements_map()); | 12248 (elements->map() == isolate->heap()->sloppy_arguments_elements_map()); |
| 12262 Handle<SeededNumberDictionary> dictionary(is_arguments | 12249 Handle<SeededNumberDictionary> dictionary(is_arguments |
| 12263 ? SeededNumberDictionary::cast(elements->get(1)) | 12250 ? SeededNumberDictionary::cast(elements->get(1)) |
| 12264 : SeededNumberDictionary::cast(*elements)); | 12251 : SeededNumberDictionary::cast(*elements)); |
| 12265 | 12252 |
| 12266 int entry = dictionary->FindEntry(index); | 12253 int entry = dictionary->FindEntry(index); |
| 12267 if (entry != SeededNumberDictionary::kNotFound) { | 12254 if (entry != SeededNumberDictionary::kNotFound) { |
| 12268 Handle<Object> element(dictionary->ValueAt(entry), isolate); | 12255 Handle<Object> element(dictionary->ValueAt(entry), isolate); |
| 12269 PropertyDetails details = dictionary->DetailsAt(entry); | 12256 PropertyDetails details = dictionary->DetailsAt(entry); |
| 12270 if (details.type() == CALLBACKS && set_mode == SET_PROPERTY) { | 12257 if (details.type() == CALLBACKS && set_mode == SET_PROPERTY) { |
| 12271 return SetElementWithCallback(object, element, index, value, object, | 12258 return SetElementWithCallback(object, element, index, value, object, |
| 12272 strict_mode); | 12259 strict_mode); |
| 12273 } else { | 12260 } else { |
| 12274 dictionary->UpdateMaxNumberKey(index); | 12261 dictionary->UpdateMaxNumberKey(index); |
| 12275 // If a value has not been initialized we allow writing to it even if it | 12262 // If a value has not been initialized we allow writing to it even if it |
| 12276 // is read-only (a declared const that has not been initialized). If a | 12263 // is read-only (a declared const that has not been initialized). If a |
| 12277 // value is being defined we skip attribute checks completely. | 12264 // value is being defined we skip attribute checks completely. |
| 12278 if (set_mode == DEFINE_PROPERTY) { | 12265 if (set_mode == DEFINE_PROPERTY) { |
| 12279 details = PropertyDetails( | 12266 details = PropertyDetails( |
| 12280 attributes, NORMAL, details.dictionary_index()); | 12267 attributes, NORMAL, details.dictionary_index()); |
| 12281 dictionary->DetailsAtPut(entry, details); | 12268 dictionary->DetailsAtPut(entry, details); |
| 12282 } else if (details.IsReadOnly() && !element->IsTheHole()) { | 12269 } else if (details.IsReadOnly() && !element->IsTheHole()) { |
| 12283 if (strict_mode == kNonStrictMode) { | 12270 if (strict_mode == SLOPPY) { |
| 12284 return isolate->factory()->undefined_value(); | 12271 return isolate->factory()->undefined_value(); |
| 12285 } else { | 12272 } else { |
| 12286 Handle<Object> number = isolate->factory()->NewNumberFromUint(index); | 12273 Handle<Object> number = isolate->factory()->NewNumberFromUint(index); |
| 12287 Handle<Object> args[2] = { number, object }; | 12274 Handle<Object> args[2] = { number, object }; |
| 12288 Handle<Object> error = | 12275 Handle<Object> error = |
| 12289 isolate->factory()->NewTypeError("strict_read_only_property", | 12276 isolate->factory()->NewTypeError("strict_read_only_property", |
| 12290 HandleVector(args, 2)); | 12277 HandleVector(args, 2)); |
| 12291 isolate->Throw(*error); | 12278 isolate->Throw(*error); |
| 12292 return Handle<Object>(); | 12279 return Handle<Object>(); |
| 12293 } | 12280 } |
| (...skipping 17 matching lines...) Expand all Loading... |
| 12311 if (check_prototype) { | 12298 if (check_prototype) { |
| 12312 bool found; | 12299 bool found; |
| 12313 Handle<Object> result = SetElementWithCallbackSetterInPrototypes(object, | 12300 Handle<Object> result = SetElementWithCallbackSetterInPrototypes(object, |
| 12314 index, value, &found, strict_mode); | 12301 index, value, &found, strict_mode); |
| 12315 if (found) return result; | 12302 if (found) return result; |
| 12316 } | 12303 } |
| 12317 | 12304 |
| 12318 // When we set the is_extensible flag to false we always force the | 12305 // When we set the is_extensible flag to false we always force the |
| 12319 // element into dictionary mode (and force them to stay there). | 12306 // element into dictionary mode (and force them to stay there). |
| 12320 if (!object->map()->is_extensible()) { | 12307 if (!object->map()->is_extensible()) { |
| 12321 if (strict_mode == kNonStrictMode) { | 12308 if (strict_mode == SLOPPY) { |
| 12322 return isolate->factory()->undefined_value(); | 12309 return isolate->factory()->undefined_value(); |
| 12323 } else { | 12310 } else { |
| 12324 Handle<Object> number = isolate->factory()->NewNumberFromUint(index); | 12311 Handle<Object> number = isolate->factory()->NewNumberFromUint(index); |
| 12325 Handle<String> name = isolate->factory()->NumberToString(number); | 12312 Handle<String> name = isolate->factory()->NumberToString(number); |
| 12326 Handle<Object> args[1] = { name }; | 12313 Handle<Object> args[1] = { name }; |
| 12327 Handle<Object> error = | 12314 Handle<Object> error = |
| 12328 isolate->factory()->NewTypeError("object_not_extensible", | 12315 isolate->factory()->NewTypeError("object_not_extensible", |
| 12329 HandleVector(args, 1)); | 12316 HandleVector(args, 1)); |
| 12330 isolate->Throw(*error); | 12317 isolate->Throw(*error); |
| 12331 return Handle<Object>(); | 12318 return Handle<Object>(); |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 12384 } | 12371 } |
| 12385 #endif | 12372 #endif |
| 12386 } | 12373 } |
| 12387 return value; | 12374 return value; |
| 12388 } | 12375 } |
| 12389 | 12376 |
| 12390 Handle<Object> JSObject::SetFastDoubleElement( | 12377 Handle<Object> JSObject::SetFastDoubleElement( |
| 12391 Handle<JSObject> object, | 12378 Handle<JSObject> object, |
| 12392 uint32_t index, | 12379 uint32_t index, |
| 12393 Handle<Object> value, | 12380 Handle<Object> value, |
| 12394 StrictModeFlag strict_mode, | 12381 StrictMode strict_mode, |
| 12395 bool check_prototype) { | 12382 bool check_prototype) { |
| 12396 ASSERT(object->HasFastDoubleElements()); | 12383 ASSERT(object->HasFastDoubleElements()); |
| 12397 | 12384 |
| 12398 Handle<FixedArrayBase> base_elms(FixedArrayBase::cast(object->elements())); | 12385 Handle<FixedArrayBase> base_elms(FixedArrayBase::cast(object->elements())); |
| 12399 uint32_t elms_length = static_cast<uint32_t>(base_elms->length()); | 12386 uint32_t elms_length = static_cast<uint32_t>(base_elms->length()); |
| 12400 | 12387 |
| 12401 // If storing to an element that isn't in the array, pass the store request | 12388 // If storing to an element that isn't in the array, pass the store request |
| 12402 // up the prototype chain before storing in the receiver's elements. | 12389 // up the prototype chain before storing in the receiver's elements. |
| 12403 if (check_prototype && | 12390 if (check_prototype && |
| 12404 (index >= elms_length || | 12391 (index >= elms_length || |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 12482 NormalizeElements(object); | 12469 NormalizeElements(object); |
| 12483 ASSERT(object->HasDictionaryElements()); | 12470 ASSERT(object->HasDictionaryElements()); |
| 12484 return SetElement(object, index, value, NONE, strict_mode, check_prototype); | 12471 return SetElement(object, index, value, NONE, strict_mode, check_prototype); |
| 12485 } | 12472 } |
| 12486 | 12473 |
| 12487 | 12474 |
| 12488 Handle<Object> JSReceiver::SetElement(Handle<JSReceiver> object, | 12475 Handle<Object> JSReceiver::SetElement(Handle<JSReceiver> object, |
| 12489 uint32_t index, | 12476 uint32_t index, |
| 12490 Handle<Object> value, | 12477 Handle<Object> value, |
| 12491 PropertyAttributes attributes, | 12478 PropertyAttributes attributes, |
| 12492 StrictModeFlag strict_mode) { | 12479 StrictMode strict_mode) { |
| 12493 if (object->IsJSProxy()) { | 12480 if (object->IsJSProxy()) { |
| 12494 return JSProxy::SetElementWithHandler( | 12481 return JSProxy::SetElementWithHandler( |
| 12495 Handle<JSProxy>::cast(object), object, index, value, strict_mode); | 12482 Handle<JSProxy>::cast(object), object, index, value, strict_mode); |
| 12496 } | 12483 } |
| 12497 return JSObject::SetElement( | 12484 return JSObject::SetElement( |
| 12498 Handle<JSObject>::cast(object), index, value, attributes, strict_mode); | 12485 Handle<JSObject>::cast(object), index, value, attributes, strict_mode); |
| 12499 } | 12486 } |
| 12500 | 12487 |
| 12501 | 12488 |
| 12502 Handle<Object> JSObject::SetOwnElement(Handle<JSObject> object, | 12489 Handle<Object> JSObject::SetOwnElement(Handle<JSObject> object, |
| 12503 uint32_t index, | 12490 uint32_t index, |
| 12504 Handle<Object> value, | 12491 Handle<Object> value, |
| 12505 StrictModeFlag strict_mode) { | 12492 StrictMode strict_mode) { |
| 12506 ASSERT(!object->HasExternalArrayElements()); | 12493 ASSERT(!object->HasExternalArrayElements()); |
| 12507 return JSObject::SetElement(object, index, value, NONE, strict_mode, false); | 12494 return JSObject::SetElement(object, index, value, NONE, strict_mode, false); |
| 12508 } | 12495 } |
| 12509 | 12496 |
| 12510 | 12497 |
| 12511 Handle<Object> JSObject::SetElement(Handle<JSObject> object, | 12498 Handle<Object> JSObject::SetElement(Handle<JSObject> object, |
| 12512 uint32_t index, | 12499 uint32_t index, |
| 12513 Handle<Object> value, | 12500 Handle<Object> value, |
| 12514 PropertyAttributes attributes, | 12501 PropertyAttributes attributes, |
| 12515 StrictModeFlag strict_mode, | 12502 StrictMode strict_mode, |
| 12516 bool check_prototype, | 12503 bool check_prototype, |
| 12517 SetPropertyMode set_mode) { | 12504 SetPropertyMode set_mode) { |
| 12518 Isolate* isolate = object->GetIsolate(); | 12505 Isolate* isolate = object->GetIsolate(); |
| 12519 | 12506 |
| 12520 if (object->HasExternalArrayElements()) { | 12507 if (object->HasExternalArrayElements()) { |
| 12521 if (!value->IsNumber() && !value->IsUndefined()) { | 12508 if (!value->IsNumber() && !value->IsUndefined()) { |
| 12522 bool has_exception; | 12509 bool has_exception; |
| 12523 Handle<Object> number = | 12510 Handle<Object> number = |
| 12524 Execution::ToNumber(isolate, value, &has_exception); | 12511 Execution::ToNumber(isolate, value, &has_exception); |
| 12525 if (has_exception) return Handle<Object>(); | 12512 if (has_exception) return Handle<Object>(); |
| 12526 value = number; | 12513 value = number; |
| 12527 } | 12514 } |
| 12528 } | 12515 } |
| 12529 | 12516 |
| 12530 // Check access rights if needed. | 12517 // Check access rights if needed. |
| 12531 if (object->IsAccessCheckNeeded()) { | 12518 if (object->IsAccessCheckNeeded()) { |
| 12532 if (!isolate->MayIndexedAccess(*object, index, v8::ACCESS_SET)) { | 12519 if (!isolate->MayIndexedAccessWrapper(object, index, v8::ACCESS_SET)) { |
| 12533 isolate->ReportFailedAccessCheck(*object, v8::ACCESS_SET); | 12520 isolate->ReportFailedAccessCheckWrapper(object, v8::ACCESS_SET); |
| 12534 RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object); | 12521 RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object); |
| 12535 return value; | 12522 return value; |
| 12536 } | 12523 } |
| 12537 } | 12524 } |
| 12538 | 12525 |
| 12539 if (object->IsJSGlobalProxy()) { | 12526 if (object->IsJSGlobalProxy()) { |
| 12540 Handle<Object> proto(object->GetPrototype(), isolate); | 12527 Handle<Object> proto(object->GetPrototype(), isolate); |
| 12541 if (proto->IsNull()) return value; | 12528 if (proto->IsNull()) return value; |
| 12542 ASSERT(proto->IsJSGlobalObject()); | 12529 ASSERT(proto->IsJSGlobalObject()); |
| 12543 return SetElement(Handle<JSObject>::cast(proto), index, value, attributes, | 12530 return SetElement(Handle<JSObject>::cast(proto), index, value, attributes, |
| (...skipping 12 matching lines...) Expand all Loading... |
| 12556 return Handle<Object>(); | 12543 return Handle<Object>(); |
| 12557 } | 12544 } |
| 12558 | 12545 |
| 12559 // Normalize the elements to enable attributes on the property. | 12546 // Normalize the elements to enable attributes on the property. |
| 12560 if ((attributes & (DONT_DELETE | DONT_ENUM | READ_ONLY)) != 0) { | 12547 if ((attributes & (DONT_DELETE | DONT_ENUM | READ_ONLY)) != 0) { |
| 12561 Handle<SeededNumberDictionary> dictionary = NormalizeElements(object); | 12548 Handle<SeededNumberDictionary> dictionary = NormalizeElements(object); |
| 12562 // Make sure that we never go back to fast case. | 12549 // Make sure that we never go back to fast case. |
| 12563 dictionary->set_requires_slow_elements(); | 12550 dictionary->set_requires_slow_elements(); |
| 12564 } | 12551 } |
| 12565 | 12552 |
| 12566 if (!(FLAG_harmony_observation && object->map()->is_observed())) { | 12553 if (!object->map()->is_observed()) { |
| 12567 return object->HasIndexedInterceptor() | 12554 return object->HasIndexedInterceptor() |
| 12568 ? SetElementWithInterceptor(object, index, value, attributes, strict_mode, | 12555 ? SetElementWithInterceptor(object, index, value, attributes, strict_mode, |
| 12569 check_prototype, | 12556 check_prototype, |
| 12570 set_mode) | 12557 set_mode) |
| 12571 : SetElementWithoutInterceptor(object, index, value, attributes, | 12558 : SetElementWithoutInterceptor(object, index, value, attributes, |
| 12572 strict_mode, | 12559 strict_mode, |
| 12573 check_prototype, | 12560 check_prototype, |
| 12574 set_mode); | 12561 set_mode); |
| 12575 } | 12562 } |
| 12576 | 12563 |
| 12577 PropertyAttributes old_attributes = object->GetLocalElementAttribute(index); | 12564 PropertyAttributes old_attributes = |
| 12565 JSReceiver::GetLocalElementAttribute(object, index); |
| 12578 Handle<Object> old_value = isolate->factory()->the_hole_value(); | 12566 Handle<Object> old_value = isolate->factory()->the_hole_value(); |
| 12579 Handle<Object> old_length_handle; | 12567 Handle<Object> old_length_handle; |
| 12580 Handle<Object> new_length_handle; | 12568 Handle<Object> new_length_handle; |
| 12581 | 12569 |
| 12582 if (old_attributes != ABSENT) { | 12570 if (old_attributes != ABSENT) { |
| 12583 if (object->GetLocalElementAccessorPair(index) == NULL) | 12571 if (object->GetLocalElementAccessorPair(index) == NULL) |
| 12584 old_value = Object::GetElement(isolate, object, index); | 12572 old_value = Object::GetElement(isolate, object, index); |
| 12585 } else if (object->IsJSArray()) { | 12573 } else if (object->IsJSArray()) { |
| 12586 // Store old array length in case adding an element grows the array. | 12574 // Store old array length in case adding an element grows the array. |
| 12587 old_length_handle = handle(Handle<JSArray>::cast(object)->length(), | 12575 old_length_handle = handle(Handle<JSArray>::cast(object)->length(), |
| 12588 isolate); | 12576 isolate); |
| 12589 } | 12577 } |
| 12590 | 12578 |
| 12591 // Check for lookup interceptor | 12579 // Check for lookup interceptor |
| 12592 Handle<Object> result = object->HasIndexedInterceptor() | 12580 Handle<Object> result = object->HasIndexedInterceptor() |
| 12593 ? SetElementWithInterceptor(object, index, value, attributes, strict_mode, | 12581 ? SetElementWithInterceptor(object, index, value, attributes, strict_mode, |
| 12594 check_prototype, | 12582 check_prototype, |
| 12595 set_mode) | 12583 set_mode) |
| 12596 : SetElementWithoutInterceptor(object, index, value, attributes, | 12584 : SetElementWithoutInterceptor(object, index, value, attributes, |
| 12597 strict_mode, | 12585 strict_mode, |
| 12598 check_prototype, | 12586 check_prototype, |
| 12599 set_mode); | 12587 set_mode); |
| 12600 RETURN_IF_EMPTY_HANDLE_VALUE(isolate, result, Handle<Object>()); | 12588 RETURN_IF_EMPTY_HANDLE_VALUE(isolate, result, Handle<Object>()); |
| 12601 | 12589 |
| 12602 Handle<String> name = isolate->factory()->Uint32ToString(index); | 12590 Handle<String> name = isolate->factory()->Uint32ToString(index); |
| 12603 PropertyAttributes new_attributes = object->GetLocalElementAttribute(index); | 12591 PropertyAttributes new_attributes = GetLocalElementAttribute(object, index); |
| 12604 if (old_attributes == ABSENT) { | 12592 if (old_attributes == ABSENT) { |
| 12605 if (object->IsJSArray() && | 12593 if (object->IsJSArray() && |
| 12606 !old_length_handle->SameValue( | 12594 !old_length_handle->SameValue( |
| 12607 Handle<JSArray>::cast(object)->length())) { | 12595 Handle<JSArray>::cast(object)->length())) { |
| 12608 new_length_handle = handle(Handle<JSArray>::cast(object)->length(), | 12596 new_length_handle = handle(Handle<JSArray>::cast(object)->length(), |
| 12609 isolate); | 12597 isolate); |
| 12610 uint32_t old_length = 0; | 12598 uint32_t old_length = 0; |
| 12611 uint32_t new_length = 0; | 12599 uint32_t new_length = 0; |
| 12612 CHECK(old_length_handle->ToArrayIndex(&old_length)); | 12600 CHECK(old_length_handle->ToArrayIndex(&old_length)); |
| 12613 CHECK(new_length_handle->ToArrayIndex(&new_length)); | 12601 CHECK(new_length_handle->ToArrayIndex(&new_length)); |
| (...skipping 24 matching lines...) Expand all Loading... |
| 12638 | 12626 |
| 12639 return result; | 12627 return result; |
| 12640 } | 12628 } |
| 12641 | 12629 |
| 12642 | 12630 |
| 12643 Handle<Object> JSObject::SetElementWithoutInterceptor( | 12631 Handle<Object> JSObject::SetElementWithoutInterceptor( |
| 12644 Handle<JSObject> object, | 12632 Handle<JSObject> object, |
| 12645 uint32_t index, | 12633 uint32_t index, |
| 12646 Handle<Object> value, | 12634 Handle<Object> value, |
| 12647 PropertyAttributes attributes, | 12635 PropertyAttributes attributes, |
| 12648 StrictModeFlag strict_mode, | 12636 StrictMode strict_mode, |
| 12649 bool check_prototype, | 12637 bool check_prototype, |
| 12650 SetPropertyMode set_mode) { | 12638 SetPropertyMode set_mode) { |
| 12651 ASSERT(object->HasDictionaryElements() || | 12639 ASSERT(object->HasDictionaryElements() || |
| 12652 object->HasDictionaryArgumentsElements() || | 12640 object->HasDictionaryArgumentsElements() || |
| 12653 (attributes & (DONT_DELETE | DONT_ENUM | READ_ONLY)) == 0); | 12641 (attributes & (DONT_DELETE | DONT_ENUM | READ_ONLY)) == 0); |
| 12654 Isolate* isolate = object->GetIsolate(); | 12642 Isolate* isolate = object->GetIsolate(); |
| 12655 if (FLAG_trace_external_array_abuse && | 12643 if (FLAG_trace_external_array_abuse && |
| 12656 IsExternalArrayElementsKind(object->GetElementsKind())) { | 12644 IsExternalArrayElementsKind(object->GetElementsKind())) { |
| 12657 CheckArrayAbuse(*object, "external elements write", index); | 12645 CheckArrayAbuse(*object, "external elements write", index); |
| 12658 } | 12646 } |
| (...skipping 27 matching lines...) Expand all Loading... |
| 12686 } | 12674 } |
| 12687 | 12675 |
| 12688 TYPED_ARRAYS(TYPED_ARRAY_CASE) | 12676 TYPED_ARRAYS(TYPED_ARRAY_CASE) |
| 12689 | 12677 |
| 12690 #undef TYPED_ARRAY_CASE | 12678 #undef TYPED_ARRAY_CASE |
| 12691 | 12679 |
| 12692 case DICTIONARY_ELEMENTS: | 12680 case DICTIONARY_ELEMENTS: |
| 12693 return SetDictionaryElement(object, index, value, attributes, strict_mode, | 12681 return SetDictionaryElement(object, index, value, attributes, strict_mode, |
| 12694 check_prototype, | 12682 check_prototype, |
| 12695 set_mode); | 12683 set_mode); |
| 12696 case NON_STRICT_ARGUMENTS_ELEMENTS: { | 12684 case SLOPPY_ARGUMENTS_ELEMENTS: { |
| 12697 Handle<FixedArray> parameter_map(FixedArray::cast(object->elements())); | 12685 Handle<FixedArray> parameter_map(FixedArray::cast(object->elements())); |
| 12698 uint32_t length = parameter_map->length(); | 12686 uint32_t length = parameter_map->length(); |
| 12699 Handle<Object> probe = index < length - 2 ? | 12687 Handle<Object> probe = index < length - 2 ? |
| 12700 Handle<Object>(parameter_map->get(index + 2), isolate) : | 12688 Handle<Object>(parameter_map->get(index + 2), isolate) : |
| 12701 Handle<Object>(); | 12689 Handle<Object>(); |
| 12702 if (!probe.is_null() && !probe->IsTheHole()) { | 12690 if (!probe.is_null() && !probe->IsTheHole()) { |
| 12703 Handle<Context> context(Context::cast(parameter_map->get(0))); | 12691 Handle<Context> context(Context::cast(parameter_map->get(0))); |
| 12704 int context_index = Handle<Smi>::cast(probe)->value(); | 12692 int context_index = Handle<Smi>::cast(probe)->value(); |
| 12705 ASSERT(!context->get(context_index)->IsTheHole()); | 12693 ASSERT(!context->get(context_index)->IsTheHole()); |
| 12706 context->set(context_index, *value); | 12694 context->set(context_index, *value); |
| (...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 12899 (IsFastSmiOrObjectElementsKind(from_kind) && | 12887 (IsFastSmiOrObjectElementsKind(from_kind) && |
| 12900 IsFastSmiOrObjectElementsKind(to_kind)) || | 12888 IsFastSmiOrObjectElementsKind(to_kind)) || |
| 12901 (from_kind == FAST_DOUBLE_ELEMENTS && | 12889 (from_kind == FAST_DOUBLE_ELEMENTS && |
| 12902 to_kind == FAST_HOLEY_DOUBLE_ELEMENTS)) { | 12890 to_kind == FAST_HOLEY_DOUBLE_ELEMENTS)) { |
| 12903 ASSERT(from_kind != TERMINAL_FAST_ELEMENTS_KIND); | 12891 ASSERT(from_kind != TERMINAL_FAST_ELEMENTS_KIND); |
| 12904 // No change is needed to the elements() buffer, the transition | 12892 // No change is needed to the elements() buffer, the transition |
| 12905 // only requires a map change. | 12893 // only requires a map change. |
| 12906 MaybeObject* maybe_new_map = GetElementsTransitionMap(isolate, to_kind); | 12894 MaybeObject* maybe_new_map = GetElementsTransitionMap(isolate, to_kind); |
| 12907 Map* new_map; | 12895 Map* new_map; |
| 12908 if (!maybe_new_map->To(&new_map)) return maybe_new_map; | 12896 if (!maybe_new_map->To(&new_map)) return maybe_new_map; |
| 12897 // TODO(verwaest): Replace by MigrateToMap. |
| 12909 set_map(new_map); | 12898 set_map(new_map); |
| 12910 if (FLAG_trace_elements_transitions) { | 12899 if (FLAG_trace_elements_transitions) { |
| 12911 FixedArrayBase* elms = FixedArrayBase::cast(elements()); | 12900 FixedArrayBase* elms = FixedArrayBase::cast(elements()); |
| 12912 PrintElementsTransition(stdout, from_kind, elms, to_kind, elms); | 12901 PrintElementsTransition(stdout, from_kind, elms, to_kind, elms); |
| 12913 } | 12902 } |
| 12914 return this; | 12903 return this; |
| 12915 } | 12904 } |
| 12916 | 12905 |
| 12917 FixedArrayBase* elms = FixedArrayBase::cast(elements()); | 12906 FixedArrayBase* elms = FixedArrayBase::cast(elements()); |
| 12918 uint32_t capacity = static_cast<uint32_t>(elms->length()); | 12907 uint32_t capacity = static_cast<uint32_t>(elms->length()); |
| (...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 13045 } | 13034 } |
| 13046 | 13035 |
| 13047 | 13036 |
| 13048 void JSObject::GetElementsCapacityAndUsage(int* capacity, int* used) { | 13037 void JSObject::GetElementsCapacityAndUsage(int* capacity, int* used) { |
| 13049 *capacity = 0; | 13038 *capacity = 0; |
| 13050 *used = 0; | 13039 *used = 0; |
| 13051 | 13040 |
| 13052 FixedArrayBase* backing_store_base = FixedArrayBase::cast(elements()); | 13041 FixedArrayBase* backing_store_base = FixedArrayBase::cast(elements()); |
| 13053 FixedArray* backing_store = NULL; | 13042 FixedArray* backing_store = NULL; |
| 13054 switch (GetElementsKind()) { | 13043 switch (GetElementsKind()) { |
| 13055 case NON_STRICT_ARGUMENTS_ELEMENTS: | 13044 case SLOPPY_ARGUMENTS_ELEMENTS: |
| 13056 backing_store_base = | 13045 backing_store_base = |
| 13057 FixedArray::cast(FixedArray::cast(backing_store_base)->get(1)); | 13046 FixedArray::cast(FixedArray::cast(backing_store_base)->get(1)); |
| 13058 backing_store = FixedArray::cast(backing_store_base); | 13047 backing_store = FixedArray::cast(backing_store_base); |
| 13059 if (backing_store->IsDictionary()) { | 13048 if (backing_store->IsDictionary()) { |
| 13060 SeededNumberDictionary* dictionary = | 13049 SeededNumberDictionary* dictionary = |
| 13061 SeededNumberDictionary::cast(backing_store); | 13050 SeededNumberDictionary::cast(backing_store); |
| 13062 *capacity = dictionary->Capacity(); | 13051 *capacity = dictionary->Capacity(); |
| 13063 *used = dictionary->NumberOfElements(); | 13052 *used = dictionary->NumberOfElements(); |
| 13064 break; | 13053 break; |
| 13065 } | 13054 } |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 13113 // External arrays are considered 100% used. | 13102 // External arrays are considered 100% used. |
| 13114 FixedArrayBase* external_array = FixedArrayBase::cast(elements()); | 13103 FixedArrayBase* external_array = FixedArrayBase::cast(elements()); |
| 13115 *capacity = external_array->length(); | 13104 *capacity = external_array->length(); |
| 13116 *used = external_array->length(); | 13105 *used = external_array->length(); |
| 13117 break; | 13106 break; |
| 13118 } | 13107 } |
| 13119 } | 13108 } |
| 13120 } | 13109 } |
| 13121 | 13110 |
| 13122 | 13111 |
| 13112 bool JSObject::WouldConvertToSlowElements(Handle<Object> key) { |
| 13113 uint32_t index; |
| 13114 if (HasFastElements() && key->ToArrayIndex(&index)) { |
| 13115 Handle<FixedArrayBase> backing_store(FixedArrayBase::cast(elements())); |
| 13116 uint32_t capacity = static_cast<uint32_t>(backing_store->length()); |
| 13117 if (index >= capacity) { |
| 13118 if ((index - capacity) >= kMaxGap) return true; |
| 13119 uint32_t new_capacity = NewElementsCapacity(index + 1); |
| 13120 return ShouldConvertToSlowElements(new_capacity); |
| 13121 } |
| 13122 } |
| 13123 return false; |
| 13124 } |
| 13125 |
| 13126 |
| 13123 bool JSObject::ShouldConvertToSlowElements(int new_capacity) { | 13127 bool JSObject::ShouldConvertToSlowElements(int new_capacity) { |
| 13124 STATIC_ASSERT(kMaxUncheckedOldFastElementsLength <= | 13128 STATIC_ASSERT(kMaxUncheckedOldFastElementsLength <= |
| 13125 kMaxUncheckedFastElementsLength); | 13129 kMaxUncheckedFastElementsLength); |
| 13126 if (new_capacity <= kMaxUncheckedOldFastElementsLength || | 13130 if (new_capacity <= kMaxUncheckedOldFastElementsLength || |
| 13127 (new_capacity <= kMaxUncheckedFastElementsLength && | 13131 (new_capacity <= kMaxUncheckedFastElementsLength && |
| 13128 GetHeap()->InNewSpace(this))) { | 13132 GetHeap()->InNewSpace(this))) { |
| 13129 return false; | 13133 return false; |
| 13130 } | 13134 } |
| 13131 // If the fast-case backing storage takes up roughly three times as | 13135 // If the fast-case backing storage takes up roughly three times as |
| 13132 // much space (in machine words) as a dictionary backing storage | 13136 // much space (in machine words) as a dictionary backing storage |
| 13133 // would, the object should have slow elements. | 13137 // would, the object should have slow elements. |
| 13134 int old_capacity = 0; | 13138 int old_capacity = 0; |
| 13135 int used_elements = 0; | 13139 int used_elements = 0; |
| 13136 GetElementsCapacityAndUsage(&old_capacity, &used_elements); | 13140 GetElementsCapacityAndUsage(&old_capacity, &used_elements); |
| 13137 int dictionary_size = SeededNumberDictionary::ComputeCapacity(used_elements) * | 13141 int dictionary_size = SeededNumberDictionary::ComputeCapacity(used_elements) * |
| 13138 SeededNumberDictionary::kEntrySize; | 13142 SeededNumberDictionary::kEntrySize; |
| 13139 return 3 * dictionary_size <= new_capacity; | 13143 return 3 * dictionary_size <= new_capacity; |
| 13140 } | 13144 } |
| 13141 | 13145 |
| 13142 | 13146 |
| 13143 bool JSObject::ShouldConvertToFastElements() { | 13147 bool JSObject::ShouldConvertToFastElements() { |
| 13144 ASSERT(HasDictionaryElements() || HasDictionaryArgumentsElements()); | 13148 ASSERT(HasDictionaryElements() || HasDictionaryArgumentsElements()); |
| 13145 // If the elements are sparse, we should not go back to fast case. | 13149 // If the elements are sparse, we should not go back to fast case. |
| 13146 if (!HasDenseElements()) return false; | 13150 if (!HasDenseElements()) return false; |
| 13147 // An object requiring access checks is never allowed to have fast | 13151 // An object requiring access checks is never allowed to have fast |
| 13148 // elements. If it had fast elements we would skip security checks. | 13152 // elements. If it had fast elements we would skip security checks. |
| 13149 if (IsAccessCheckNeeded()) return false; | 13153 if (IsAccessCheckNeeded()) return false; |
| 13150 // Observed objects may not go to fast mode because they rely on map checks, | 13154 // Observed objects may not go to fast mode because they rely on map checks, |
| 13151 // and for fast element accesses we sometimes check element kinds only. | 13155 // and for fast element accesses we sometimes check element kinds only. |
| 13152 if (FLAG_harmony_observation && map()->is_observed()) return false; | 13156 if (map()->is_observed()) return false; |
| 13153 | 13157 |
| 13154 FixedArray* elements = FixedArray::cast(this->elements()); | 13158 FixedArray* elements = FixedArray::cast(this->elements()); |
| 13155 SeededNumberDictionary* dictionary = NULL; | 13159 SeededNumberDictionary* dictionary = NULL; |
| 13156 if (elements->map() == GetHeap()->non_strict_arguments_elements_map()) { | 13160 if (elements->map() == GetHeap()->sloppy_arguments_elements_map()) { |
| 13157 dictionary = SeededNumberDictionary::cast(elements->get(1)); | 13161 dictionary = SeededNumberDictionary::cast(elements->get(1)); |
| 13158 } else { | 13162 } else { |
| 13159 dictionary = SeededNumberDictionary::cast(elements); | 13163 dictionary = SeededNumberDictionary::cast(elements); |
| 13160 } | 13164 } |
| 13161 // If an element has been added at a very high index in the elements | 13165 // If an element has been added at a very high index in the elements |
| 13162 // dictionary, we cannot go back to fast case. | 13166 // dictionary, we cannot go back to fast case. |
| 13163 if (dictionary->requires_slow_elements()) return false; | 13167 if (dictionary->requires_slow_elements()) return false; |
| 13164 // If the dictionary backing storage takes up roughly half as much | 13168 // If the dictionary backing storage takes up roughly half as much |
| 13165 // space (in machine words) as a fast-case backing storage would, | 13169 // space (in machine words) as a fast-case backing storage would, |
| 13166 // the object should have fast elements. | 13170 // the object should have fast elements. |
| (...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 13336 return GetPropertyPostInterceptor(object, receiver, name, attributes); | 13340 return GetPropertyPostInterceptor(object, receiver, name, attributes); |
| 13337 } | 13341 } |
| 13338 | 13342 |
| 13339 | 13343 |
| 13340 bool JSObject::HasRealNamedProperty(Handle<JSObject> object, | 13344 bool JSObject::HasRealNamedProperty(Handle<JSObject> object, |
| 13341 Handle<Name> key) { | 13345 Handle<Name> key) { |
| 13342 Isolate* isolate = object->GetIsolate(); | 13346 Isolate* isolate = object->GetIsolate(); |
| 13343 SealHandleScope shs(isolate); | 13347 SealHandleScope shs(isolate); |
| 13344 // Check access rights if needed. | 13348 // Check access rights if needed. |
| 13345 if (object->IsAccessCheckNeeded()) { | 13349 if (object->IsAccessCheckNeeded()) { |
| 13346 if (!isolate->MayNamedAccess(*object, *key, v8::ACCESS_HAS)) { | 13350 if (!isolate->MayNamedAccessWrapper(object, key, v8::ACCESS_HAS)) { |
| 13347 isolate->ReportFailedAccessCheck(*object, v8::ACCESS_HAS); | 13351 isolate->ReportFailedAccessCheckWrapper(object, v8::ACCESS_HAS); |
| 13348 return false; | 13352 return false; |
| 13349 } | 13353 } |
| 13350 } | 13354 } |
| 13351 | 13355 |
| 13352 LookupResult result(isolate); | 13356 LookupResult result(isolate); |
| 13353 object->LocalLookupRealNamedProperty(*key, &result); | 13357 object->LocalLookupRealNamedProperty(*key, &result); |
| 13354 return result.IsFound() && !result.IsInterceptor(); | 13358 return result.IsFound() && !result.IsInterceptor(); |
| 13355 } | 13359 } |
| 13356 | 13360 |
| 13357 | 13361 |
| 13358 bool JSObject::HasRealElementProperty(Handle<JSObject> object, uint32_t index) { | 13362 bool JSObject::HasRealElementProperty(Handle<JSObject> object, uint32_t index) { |
| 13359 Isolate* isolate = object->GetIsolate(); | 13363 Isolate* isolate = object->GetIsolate(); |
| 13360 SealHandleScope shs(isolate); | 13364 HandleScope scope(isolate); |
| 13361 // Check access rights if needed. | 13365 // Check access rights if needed. |
| 13362 if (object->IsAccessCheckNeeded()) { | 13366 if (object->IsAccessCheckNeeded()) { |
| 13363 if (!isolate->MayIndexedAccess(*object, index, v8::ACCESS_HAS)) { | 13367 if (!isolate->MayIndexedAccessWrapper(object, index, v8::ACCESS_HAS)) { |
| 13364 isolate->ReportFailedAccessCheck(*object, v8::ACCESS_HAS); | 13368 isolate->ReportFailedAccessCheckWrapper(object, v8::ACCESS_HAS); |
| 13365 return false; | 13369 return false; |
| 13366 } | 13370 } |
| 13367 } | 13371 } |
| 13368 | 13372 |
| 13369 if (object->IsJSGlobalProxy()) { | 13373 if (object->IsJSGlobalProxy()) { |
| 13370 HandleScope scope(isolate); | 13374 HandleScope scope(isolate); |
| 13371 Handle<Object> proto(object->GetPrototype(), isolate); | 13375 Handle<Object> proto(object->GetPrototype(), isolate); |
| 13372 if (proto->IsNull()) return false; | 13376 if (proto->IsNull()) return false; |
| 13373 ASSERT(proto->IsJSGlobalObject()); | 13377 ASSERT(proto->IsJSGlobalObject()); |
| 13374 return HasRealElementProperty(Handle<JSObject>::cast(proto), index); | 13378 return HasRealElementProperty(Handle<JSObject>::cast(proto), index); |
| 13375 } | 13379 } |
| 13376 | 13380 |
| 13377 return object->GetElementAttributeWithoutInterceptor( | 13381 return GetElementAttributeWithoutInterceptor( |
| 13378 *object, index, false) != ABSENT; | 13382 object, object, index, false) != ABSENT; |
| 13379 } | 13383 } |
| 13380 | 13384 |
| 13381 | 13385 |
| 13382 bool JSObject::HasRealNamedCallbackProperty(Handle<JSObject> object, | 13386 bool JSObject::HasRealNamedCallbackProperty(Handle<JSObject> object, |
| 13383 Handle<Name> key) { | 13387 Handle<Name> key) { |
| 13384 Isolate* isolate = object->GetIsolate(); | 13388 Isolate* isolate = object->GetIsolate(); |
| 13385 SealHandleScope shs(isolate); | 13389 SealHandleScope shs(isolate); |
| 13386 // Check access rights if needed. | 13390 // Check access rights if needed. |
| 13387 if (object->IsAccessCheckNeeded()) { | 13391 if (object->IsAccessCheckNeeded()) { |
| 13388 if (!isolate->MayNamedAccess(*object, *key, v8::ACCESS_HAS)) { | 13392 if (!isolate->MayNamedAccessWrapper(object, key, v8::ACCESS_HAS)) { |
| 13389 isolate->ReportFailedAccessCheck(*object, v8::ACCESS_HAS); | 13393 isolate->ReportFailedAccessCheckWrapper(object, v8::ACCESS_HAS); |
| 13390 return false; | 13394 return false; |
| 13391 } | 13395 } |
| 13392 } | 13396 } |
| 13393 | 13397 |
| 13394 LookupResult result(isolate); | 13398 LookupResult result(isolate); |
| 13395 object->LocalLookupRealNamedProperty(*key, &result); | 13399 object->LocalLookupRealNamedProperty(*key, &result); |
| 13396 return result.IsPropertyCallbacks(); | 13400 return result.IsPropertyCallbacks(); |
| 13397 } | 13401 } |
| 13398 | 13402 |
| 13399 | 13403 |
| (...skipping 226 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 13626 | 13630 |
| 13627 case DICTIONARY_ELEMENTS: { | 13631 case DICTIONARY_ELEMENTS: { |
| 13628 if (storage != NULL) { | 13632 if (storage != NULL) { |
| 13629 element_dictionary()->CopyKeysTo(storage, | 13633 element_dictionary()->CopyKeysTo(storage, |
| 13630 filter, | 13634 filter, |
| 13631 SeededNumberDictionary::SORTED); | 13635 SeededNumberDictionary::SORTED); |
| 13632 } | 13636 } |
| 13633 counter += element_dictionary()->NumberOfElementsFilterAttributes(filter); | 13637 counter += element_dictionary()->NumberOfElementsFilterAttributes(filter); |
| 13634 break; | 13638 break; |
| 13635 } | 13639 } |
| 13636 case NON_STRICT_ARGUMENTS_ELEMENTS: { | 13640 case SLOPPY_ARGUMENTS_ELEMENTS: { |
| 13637 FixedArray* parameter_map = FixedArray::cast(elements()); | 13641 FixedArray* parameter_map = FixedArray::cast(elements()); |
| 13638 int mapped_length = parameter_map->length() - 2; | 13642 int mapped_length = parameter_map->length() - 2; |
| 13639 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); | 13643 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); |
| 13640 if (arguments->IsDictionary()) { | 13644 if (arguments->IsDictionary()) { |
| 13641 // Copy the keys from arguments first, because Dictionary::CopyKeysTo | 13645 // Copy the keys from arguments first, because Dictionary::CopyKeysTo |
| 13642 // will insert in storage starting at index 0. | 13646 // will insert in storage starting at index 0. |
| 13643 SeededNumberDictionary* dictionary = | 13647 SeededNumberDictionary* dictionary = |
| 13644 SeededNumberDictionary::cast(arguments); | 13648 SeededNumberDictionary::cast(arguments); |
| 13645 if (storage != NULL) { | 13649 if (storage != NULL) { |
| 13646 dictionary->CopyKeysTo( | 13650 dictionary->CopyKeysTo( |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 13724 String* string_; | 13728 String* string_; |
| 13725 uint32_t hash_; | 13729 uint32_t hash_; |
| 13726 }; | 13730 }; |
| 13727 | 13731 |
| 13728 | 13732 |
| 13729 // StringSharedKeys are used as keys in the eval cache. | 13733 // StringSharedKeys are used as keys in the eval cache. |
| 13730 class StringSharedKey : public HashTableKey { | 13734 class StringSharedKey : public HashTableKey { |
| 13731 public: | 13735 public: |
| 13732 StringSharedKey(String* source, | 13736 StringSharedKey(String* source, |
| 13733 SharedFunctionInfo* shared, | 13737 SharedFunctionInfo* shared, |
| 13734 LanguageMode language_mode, | 13738 StrictMode strict_mode, |
| 13735 int scope_position) | 13739 int scope_position) |
| 13736 : source_(source), | 13740 : source_(source), |
| 13737 shared_(shared), | 13741 shared_(shared), |
| 13738 language_mode_(language_mode), | 13742 strict_mode_(strict_mode), |
| 13739 scope_position_(scope_position) { } | 13743 scope_position_(scope_position) { } |
| 13740 | 13744 |
| 13741 bool IsMatch(Object* other) { | 13745 bool IsMatch(Object* other) { |
| 13742 if (!other->IsFixedArray()) return false; | 13746 if (!other->IsFixedArray()) return false; |
| 13743 FixedArray* other_array = FixedArray::cast(other); | 13747 FixedArray* other_array = FixedArray::cast(other); |
| 13744 SharedFunctionInfo* shared = SharedFunctionInfo::cast(other_array->get(0)); | 13748 SharedFunctionInfo* shared = SharedFunctionInfo::cast(other_array->get(0)); |
| 13745 if (shared != shared_) return false; | 13749 if (shared != shared_) return false; |
| 13746 int language_unchecked = Smi::cast(other_array->get(2))->value(); | 13750 int strict_unchecked = Smi::cast(other_array->get(2))->value(); |
| 13747 ASSERT(language_unchecked == CLASSIC_MODE || | 13751 ASSERT(strict_unchecked == SLOPPY || strict_unchecked == STRICT); |
| 13748 language_unchecked == STRICT_MODE || | 13752 StrictMode strict_mode = static_cast<StrictMode>(strict_unchecked); |
| 13749 language_unchecked == EXTENDED_MODE); | 13753 if (strict_mode != strict_mode_) return false; |
| 13750 LanguageMode language_mode = static_cast<LanguageMode>(language_unchecked); | |
| 13751 if (language_mode != language_mode_) return false; | |
| 13752 int scope_position = Smi::cast(other_array->get(3))->value(); | 13754 int scope_position = Smi::cast(other_array->get(3))->value(); |
| 13753 if (scope_position != scope_position_) return false; | 13755 if (scope_position != scope_position_) return false; |
| 13754 String* source = String::cast(other_array->get(1)); | 13756 String* source = String::cast(other_array->get(1)); |
| 13755 return source->Equals(source_); | 13757 return source->Equals(source_); |
| 13756 } | 13758 } |
| 13757 | 13759 |
| 13758 static uint32_t StringSharedHashHelper(String* source, | 13760 static uint32_t StringSharedHashHelper(String* source, |
| 13759 SharedFunctionInfo* shared, | 13761 SharedFunctionInfo* shared, |
| 13760 LanguageMode language_mode, | 13762 StrictMode strict_mode, |
| 13761 int scope_position) { | 13763 int scope_position) { |
| 13762 uint32_t hash = source->Hash(); | 13764 uint32_t hash = source->Hash(); |
| 13763 if (shared->HasSourceCode()) { | 13765 if (shared->HasSourceCode()) { |
| 13764 // Instead of using the SharedFunctionInfo pointer in the hash | 13766 // Instead of using the SharedFunctionInfo pointer in the hash |
| 13765 // code computation, we use a combination of the hash of the | 13767 // code computation, we use a combination of the hash of the |
| 13766 // script source code and the start position of the calling scope. | 13768 // script source code and the start position of the calling scope. |
| 13767 // We do this to ensure that the cache entries can survive garbage | 13769 // We do this to ensure that the cache entries can survive garbage |
| 13768 // collection. | 13770 // collection. |
| 13769 Script* script = Script::cast(shared->script()); | 13771 Script* script = Script::cast(shared->script()); |
| 13770 hash ^= String::cast(script->source())->Hash(); | 13772 hash ^= String::cast(script->source())->Hash(); |
| 13771 if (language_mode == STRICT_MODE) hash ^= 0x8000; | 13773 if (strict_mode == STRICT) hash ^= 0x8000; |
| 13772 if (language_mode == EXTENDED_MODE) hash ^= 0x0080; | |
| 13773 hash += scope_position; | 13774 hash += scope_position; |
| 13774 } | 13775 } |
| 13775 return hash; | 13776 return hash; |
| 13776 } | 13777 } |
| 13777 | 13778 |
| 13778 uint32_t Hash() { | 13779 uint32_t Hash() { |
| 13779 return StringSharedHashHelper( | 13780 return StringSharedHashHelper( |
| 13780 source_, shared_, language_mode_, scope_position_); | 13781 source_, shared_, strict_mode_, scope_position_); |
| 13781 } | 13782 } |
| 13782 | 13783 |
| 13783 uint32_t HashForObject(Object* obj) { | 13784 uint32_t HashForObject(Object* obj) { |
| 13784 FixedArray* other_array = FixedArray::cast(obj); | 13785 FixedArray* other_array = FixedArray::cast(obj); |
| 13785 SharedFunctionInfo* shared = SharedFunctionInfo::cast(other_array->get(0)); | 13786 SharedFunctionInfo* shared = SharedFunctionInfo::cast(other_array->get(0)); |
| 13786 String* source = String::cast(other_array->get(1)); | 13787 String* source = String::cast(other_array->get(1)); |
| 13787 int language_unchecked = Smi::cast(other_array->get(2))->value(); | 13788 int strict_unchecked = Smi::cast(other_array->get(2))->value(); |
| 13788 ASSERT(language_unchecked == CLASSIC_MODE || | 13789 ASSERT(strict_unchecked == SLOPPY || strict_unchecked == STRICT); |
| 13789 language_unchecked == STRICT_MODE || | 13790 StrictMode strict_mode = static_cast<StrictMode>(strict_unchecked); |
| 13790 language_unchecked == EXTENDED_MODE); | |
| 13791 LanguageMode language_mode = static_cast<LanguageMode>(language_unchecked); | |
| 13792 int scope_position = Smi::cast(other_array->get(3))->value(); | 13791 int scope_position = Smi::cast(other_array->get(3))->value(); |
| 13793 return StringSharedHashHelper( | 13792 return StringSharedHashHelper( |
| 13794 source, shared, language_mode, scope_position); | 13793 source, shared, strict_mode, scope_position); |
| 13795 } | 13794 } |
| 13796 | 13795 |
| 13797 MUST_USE_RESULT MaybeObject* AsObject(Heap* heap) { | 13796 MUST_USE_RESULT MaybeObject* AsObject(Heap* heap) { |
| 13798 Object* obj; | 13797 Object* obj; |
| 13799 { MaybeObject* maybe_obj = heap->AllocateFixedArray(4); | 13798 { MaybeObject* maybe_obj = heap->AllocateFixedArray(4); |
| 13800 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 13799 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 13801 } | 13800 } |
| 13802 FixedArray* other_array = FixedArray::cast(obj); | 13801 FixedArray* other_array = FixedArray::cast(obj); |
| 13803 other_array->set(0, shared_); | 13802 other_array->set(0, shared_); |
| 13804 other_array->set(1, source_); | 13803 other_array->set(1, source_); |
| 13805 other_array->set(2, Smi::FromInt(language_mode_)); | 13804 other_array->set(2, Smi::FromInt(strict_mode_)); |
| 13806 other_array->set(3, Smi::FromInt(scope_position_)); | 13805 other_array->set(3, Smi::FromInt(scope_position_)); |
| 13807 return other_array; | 13806 return other_array; |
| 13808 } | 13807 } |
| 13809 | 13808 |
| 13810 private: | 13809 private: |
| 13811 String* source_; | 13810 String* source_; |
| 13812 SharedFunctionInfo* shared_; | 13811 SharedFunctionInfo* shared_; |
| 13813 LanguageMode language_mode_; | 13812 StrictMode strict_mode_; |
| 13814 int scope_position_; | 13813 int scope_position_; |
| 13815 }; | 13814 }; |
| 13816 | 13815 |
| 13817 | 13816 |
| 13818 // RegExpKey carries the source and flags of a regular expression as key. | 13817 // RegExpKey carries the source and flags of a regular expression as key. |
| 13819 class RegExpKey : public HashTableKey { | 13818 class RegExpKey : public HashTableKey { |
| 13820 public: | 13819 public: |
| 13821 RegExpKey(String* string, JSRegExp::Flags flags) | 13820 RegExpKey(String* string, JSRegExp::Flags flags) |
| 13822 : string_(string), | 13821 : string_(string), |
| 13823 flags_(Smi::FromInt(flags.value())) { } | 13822 flags_(Smi::FromInt(flags.value())) { } |
| (...skipping 615 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 14439 } | 14438 } |
| 14440 | 14439 |
| 14441 | 14440 |
| 14442 // Collects all defined (non-hole) and non-undefined (array) elements at | 14441 // Collects all defined (non-hole) and non-undefined (array) elements at |
| 14443 // the start of the elements array. | 14442 // the start of the elements array. |
| 14444 // If the object is in dictionary mode, it is converted to fast elements | 14443 // If the object is in dictionary mode, it is converted to fast elements |
| 14445 // mode. | 14444 // mode. |
| 14446 Handle<Object> JSObject::PrepareElementsForSort(Handle<JSObject> object, | 14445 Handle<Object> JSObject::PrepareElementsForSort(Handle<JSObject> object, |
| 14447 uint32_t limit) { | 14446 uint32_t limit) { |
| 14448 Isolate* isolate = object->GetIsolate(); | 14447 Isolate* isolate = object->GetIsolate(); |
| 14448 if (object->HasSloppyArgumentsElements() || |
| 14449 object->map()->is_observed()) { |
| 14450 return handle(Smi::FromInt(-1), isolate); |
| 14451 } |
| 14449 | 14452 |
| 14450 ASSERT(!object->map()->is_observed()); | |
| 14451 if (object->HasDictionaryElements()) { | 14453 if (object->HasDictionaryElements()) { |
| 14452 // Convert to fast elements containing only the existing properties. | 14454 // Convert to fast elements containing only the existing properties. |
| 14453 // Ordering is irrelevant, since we are going to sort anyway. | 14455 // Ordering is irrelevant, since we are going to sort anyway. |
| 14454 Handle<SeededNumberDictionary> dict(object->element_dictionary()); | 14456 Handle<SeededNumberDictionary> dict(object->element_dictionary()); |
| 14455 if (object->IsJSArray() || dict->requires_slow_elements() || | 14457 if (object->IsJSArray() || dict->requires_slow_elements() || |
| 14456 dict->max_number_key() >= limit) { | 14458 dict->max_number_key() >= limit) { |
| 14457 return JSObject::PrepareSlowElementsForSort(object, limit); | 14459 return JSObject::PrepareSlowElementsForSort(object, limit); |
| 14458 } | 14460 } |
| 14459 // Convert to fast elements. | 14461 // Convert to fast elements. |
| 14460 | 14462 |
| (...skipping 535 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 14996 | 14998 |
| 14997 // Add the new string and return it along with the string table. | 14999 // Add the new string and return it along with the string table. |
| 14998 entry = table->FindInsertionEntry(key->Hash()); | 15000 entry = table->FindInsertionEntry(key->Hash()); |
| 14999 table->set(EntryToIndex(entry), string); | 15001 table->set(EntryToIndex(entry), string); |
| 15000 table->ElementAdded(); | 15002 table->ElementAdded(); |
| 15001 *s = string; | 15003 *s = string; |
| 15002 return table; | 15004 return table; |
| 15003 } | 15005 } |
| 15004 | 15006 |
| 15005 | 15007 |
| 15006 // The key for the script compilation cache is dependent on the mode flags, | |
| 15007 // because they change the global language mode and thus binding behaviour. | |
| 15008 // If flags change at some point, we must ensure that we do not hit the cache | |
| 15009 // for code compiled with different settings. | |
| 15010 static LanguageMode CurrentGlobalLanguageMode() { | |
| 15011 return FLAG_use_strict | |
| 15012 ? (FLAG_harmony_scoping ? EXTENDED_MODE : STRICT_MODE) | |
| 15013 : CLASSIC_MODE; | |
| 15014 } | |
| 15015 | |
| 15016 | |
| 15017 Object* CompilationCacheTable::Lookup(String* src, Context* context) { | 15008 Object* CompilationCacheTable::Lookup(String* src, Context* context) { |
| 15018 SharedFunctionInfo* shared = context->closure()->shared(); | 15009 SharedFunctionInfo* shared = context->closure()->shared(); |
| 15019 StringSharedKey key(src, | 15010 StringSharedKey key(src, |
| 15020 shared, | 15011 shared, |
| 15021 CurrentGlobalLanguageMode(), | 15012 FLAG_use_strict ? STRICT : SLOPPY, |
| 15022 RelocInfo::kNoPosition); | 15013 RelocInfo::kNoPosition); |
| 15023 int entry = FindEntry(&key); | 15014 int entry = FindEntry(&key); |
| 15024 if (entry == kNotFound) return GetHeap()->undefined_value(); | 15015 if (entry == kNotFound) return GetHeap()->undefined_value(); |
| 15025 return get(EntryToIndex(entry) + 1); | 15016 return get(EntryToIndex(entry) + 1); |
| 15026 } | 15017 } |
| 15027 | 15018 |
| 15028 | 15019 |
| 15029 Object* CompilationCacheTable::LookupEval(String* src, | 15020 Object* CompilationCacheTable::LookupEval(String* src, |
| 15030 Context* context, | 15021 Context* context, |
| 15031 LanguageMode language_mode, | 15022 StrictMode strict_mode, |
| 15032 int scope_position) { | 15023 int scope_position) { |
| 15033 StringSharedKey key(src, | 15024 StringSharedKey key(src, |
| 15034 context->closure()->shared(), | 15025 context->closure()->shared(), |
| 15035 language_mode, | 15026 strict_mode, |
| 15036 scope_position); | 15027 scope_position); |
| 15037 int entry = FindEntry(&key); | 15028 int entry = FindEntry(&key); |
| 15038 if (entry == kNotFound) return GetHeap()->undefined_value(); | 15029 if (entry == kNotFound) return GetHeap()->undefined_value(); |
| 15039 return get(EntryToIndex(entry) + 1); | 15030 return get(EntryToIndex(entry) + 1); |
| 15040 } | 15031 } |
| 15041 | 15032 |
| 15042 | 15033 |
| 15043 Object* CompilationCacheTable::LookupRegExp(String* src, | 15034 Object* CompilationCacheTable::LookupRegExp(String* src, |
| 15044 JSRegExp::Flags flags) { | 15035 JSRegExp::Flags flags) { |
| 15045 RegExpKey key(src, flags); | 15036 RegExpKey key(src, flags); |
| 15046 int entry = FindEntry(&key); | 15037 int entry = FindEntry(&key); |
| 15047 if (entry == kNotFound) return GetHeap()->undefined_value(); | 15038 if (entry == kNotFound) return GetHeap()->undefined_value(); |
| 15048 return get(EntryToIndex(entry) + 1); | 15039 return get(EntryToIndex(entry) + 1); |
| 15049 } | 15040 } |
| 15050 | 15041 |
| 15051 | 15042 |
| 15052 MaybeObject* CompilationCacheTable::Put(String* src, | 15043 MaybeObject* CompilationCacheTable::Put(String* src, |
| 15053 Context* context, | 15044 Context* context, |
| 15054 Object* value) { | 15045 Object* value) { |
| 15055 SharedFunctionInfo* shared = context->closure()->shared(); | 15046 SharedFunctionInfo* shared = context->closure()->shared(); |
| 15056 StringSharedKey key(src, | 15047 StringSharedKey key(src, |
| 15057 shared, | 15048 shared, |
| 15058 CurrentGlobalLanguageMode(), | 15049 FLAG_use_strict ? STRICT : SLOPPY, |
| 15059 RelocInfo::kNoPosition); | 15050 RelocInfo::kNoPosition); |
| 15060 CompilationCacheTable* cache; | 15051 CompilationCacheTable* cache; |
| 15061 MaybeObject* maybe_cache = EnsureCapacity(1, &key); | 15052 MaybeObject* maybe_cache = EnsureCapacity(1, &key); |
| 15062 if (!maybe_cache->To(&cache)) return maybe_cache; | 15053 if (!maybe_cache->To(&cache)) return maybe_cache; |
| 15063 | 15054 |
| 15064 Object* k; | 15055 Object* k; |
| 15065 MaybeObject* maybe_k = key.AsObject(GetHeap()); | 15056 MaybeObject* maybe_k = key.AsObject(GetHeap()); |
| 15066 if (!maybe_k->To(&k)) return maybe_k; | 15057 if (!maybe_k->To(&k)) return maybe_k; |
| 15067 | 15058 |
| 15068 int entry = cache->FindInsertionEntry(key.Hash()); | 15059 int entry = cache->FindInsertionEntry(key.Hash()); |
| 15069 cache->set(EntryToIndex(entry), k); | 15060 cache->set(EntryToIndex(entry), k); |
| 15070 cache->set(EntryToIndex(entry) + 1, value); | 15061 cache->set(EntryToIndex(entry) + 1, value); |
| 15071 cache->ElementAdded(); | 15062 cache->ElementAdded(); |
| 15072 return cache; | 15063 return cache; |
| 15073 } | 15064 } |
| 15074 | 15065 |
| 15075 | 15066 |
| 15076 MaybeObject* CompilationCacheTable::PutEval(String* src, | 15067 MaybeObject* CompilationCacheTable::PutEval(String* src, |
| 15077 Context* context, | 15068 Context* context, |
| 15078 SharedFunctionInfo* value, | 15069 SharedFunctionInfo* value, |
| 15079 int scope_position) { | 15070 int scope_position) { |
| 15080 StringSharedKey key(src, | 15071 StringSharedKey key(src, |
| 15081 context->closure()->shared(), | 15072 context->closure()->shared(), |
| 15082 value->language_mode(), | 15073 value->strict_mode(), |
| 15083 scope_position); | 15074 scope_position); |
| 15084 Object* obj; | 15075 Object* obj; |
| 15085 { MaybeObject* maybe_obj = EnsureCapacity(1, &key); | 15076 { MaybeObject* maybe_obj = EnsureCapacity(1, &key); |
| 15086 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 15077 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 15087 } | 15078 } |
| 15088 | 15079 |
| 15089 CompilationCacheTable* cache = | 15080 CompilationCacheTable* cache = |
| 15090 reinterpret_cast<CompilationCacheTable*>(obj); | 15081 reinterpret_cast<CompilationCacheTable*>(obj); |
| 15091 int entry = cache->FindInsertionEntry(key.Hash()); | 15082 int entry = cache->FindInsertionEntry(key.Hash()); |
| 15092 | 15083 |
| (...skipping 422 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 15515 if ((attr & filter) == 0) result++; | 15506 if ((attr & filter) == 0) result++; |
| 15516 } | 15507 } |
| 15517 } | 15508 } |
| 15518 return result; | 15509 return result; |
| 15519 } | 15510 } |
| 15520 | 15511 |
| 15521 | 15512 |
| 15522 template<typename Shape, typename Key> | 15513 template<typename Shape, typename Key> |
| 15523 int Dictionary<Shape, Key>::NumberOfEnumElements() { | 15514 int Dictionary<Shape, Key>::NumberOfEnumElements() { |
| 15524 return NumberOfElementsFilterAttributes( | 15515 return NumberOfElementsFilterAttributes( |
| 15525 static_cast<PropertyAttributes>(DONT_ENUM)); | 15516 static_cast<PropertyAttributes>(DONT_ENUM | SYMBOLIC)); |
| 15526 } | 15517 } |
| 15527 | 15518 |
| 15528 | 15519 |
| 15529 template<typename Shape, typename Key> | 15520 template<typename Shape, typename Key> |
| 15530 void Dictionary<Shape, Key>::CopyKeysTo( | 15521 void Dictionary<Shape, Key>::CopyKeysTo( |
| 15531 FixedArray* storage, | 15522 FixedArray* storage, |
| 15532 PropertyAttributes filter, | 15523 PropertyAttributes filter, |
| 15533 typename Dictionary<Shape, Key>::SortMode sort_mode) { | 15524 typename Dictionary<Shape, Key>::SortMode sort_mode) { |
| 15534 ASSERT(storage->length() >= NumberOfElementsFilterAttributes(filter)); | 15525 ASSERT(storage->length() >= NumberOfElementsFilterAttributes(filter)); |
| 15535 int capacity = HashTable<Shape, Key>::Capacity(); | 15526 int capacity = HashTable<Shape, Key>::Capacity(); |
| 15536 int index = 0; | 15527 int index = 0; |
| 15537 for (int i = 0; i < capacity; i++) { | 15528 for (int i = 0; i < capacity; i++) { |
| 15538 Object* k = HashTable<Shape, Key>::KeyAt(i); | 15529 Object* k = HashTable<Shape, Key>::KeyAt(i); |
| 15539 if (HashTable<Shape, Key>::IsKey(k) && !FilterKey(k, filter)) { | 15530 if (HashTable<Shape, Key>::IsKey(k) && !FilterKey(k, filter)) { |
| 15540 PropertyDetails details = DetailsAt(i); | 15531 PropertyDetails details = DetailsAt(i); |
| 15541 if (details.IsDeleted()) continue; | 15532 if (details.IsDeleted()) continue; |
| 15542 PropertyAttributes attr = details.attributes(); | 15533 PropertyAttributes attr = details.attributes(); |
| 15543 if ((attr & filter) == 0) storage->set(index++, k); | 15534 if ((attr & filter) == 0) storage->set(index++, k); |
| 15544 } | 15535 } |
| 15545 } | 15536 } |
| 15546 if (sort_mode == Dictionary<Shape, Key>::SORTED) { | 15537 if (sort_mode == Dictionary<Shape, Key>::SORTED) { |
| 15547 storage->SortPairs(storage, index); | 15538 storage->SortPairs(storage, index); |
| 15548 } | 15539 } |
| 15549 ASSERT(storage->length() >= index); | 15540 ASSERT(storage->length() >= index); |
| 15550 } | 15541 } |
| 15551 | 15542 |
| 15552 | 15543 |
| 15553 FixedArray* NameDictionary::CopyEnumKeysTo(FixedArray* storage) { | 15544 struct EnumIndexComparator { |
| 15545 explicit EnumIndexComparator(NameDictionary* dict) : dict(dict) { } |
| 15546 bool operator() (Smi* a, Smi* b) { |
| 15547 PropertyDetails da(dict->DetailsAt(a->value())); |
| 15548 PropertyDetails db(dict->DetailsAt(b->value())); |
| 15549 return da.dictionary_index() < db.dictionary_index(); |
| 15550 } |
| 15551 NameDictionary* dict; |
| 15552 }; |
| 15553 |
| 15554 |
| 15555 void NameDictionary::CopyEnumKeysTo(FixedArray* storage) { |
| 15554 int length = storage->length(); | 15556 int length = storage->length(); |
| 15555 ASSERT(length >= NumberOfEnumElements()); | |
| 15556 Heap* heap = GetHeap(); | |
| 15557 Object* undefined_value = heap->undefined_value(); | |
| 15558 int capacity = Capacity(); | 15557 int capacity = Capacity(); |
| 15559 int properties = 0; | 15558 int properties = 0; |
| 15560 | |
| 15561 // Fill in the enumeration array by assigning enumerable keys at their | |
| 15562 // enumeration index. This will leave holes in the array if there are keys | |
| 15563 // that are deleted or not enumerable. | |
| 15564 for (int i = 0; i < capacity; i++) { | 15559 for (int i = 0; i < capacity; i++) { |
| 15565 Object* k = KeyAt(i); | 15560 Object* k = KeyAt(i); |
| 15566 if (IsKey(k) && !k->IsSymbol()) { | 15561 if (IsKey(k) && !k->IsSymbol()) { |
| 15567 PropertyDetails details = DetailsAt(i); | 15562 PropertyDetails details = DetailsAt(i); |
| 15568 if (details.IsDeleted() || details.IsDontEnum()) continue; | 15563 if (details.IsDeleted() || details.IsDontEnum()) continue; |
| 15564 storage->set(properties, Smi::FromInt(i)); |
| 15569 properties++; | 15565 properties++; |
| 15570 storage->set(details.dictionary_index() - 1, k); | |
| 15571 if (properties == length) break; | 15566 if (properties == length) break; |
| 15572 } | 15567 } |
| 15573 } | 15568 } |
| 15574 | 15569 EnumIndexComparator cmp(this); |
| 15575 // There are holes in the enumeration array if less properties were assigned | 15570 Smi** start = reinterpret_cast<Smi**>(storage->GetFirstElementAddress()); |
| 15576 // than the length of the array. If so, crunch all the existing properties | 15571 std::sort(start, start + length, cmp); |
| 15577 // together by shifting them to the left (maintaining the enumeration order), | 15572 for (int i = 0; i < length; i++) { |
| 15578 // and trimming of the right side of the array. | 15573 int index = Smi::cast(storage->get(i))->value(); |
| 15579 if (properties < length) { | 15574 storage->set(i, KeyAt(index)); |
| 15580 if (properties == 0) return heap->empty_fixed_array(); | |
| 15581 properties = 0; | |
| 15582 for (int i = 0; i < length; ++i) { | |
| 15583 Object* value = storage->get(i); | |
| 15584 if (value != undefined_value) { | |
| 15585 storage->set(properties, value); | |
| 15586 ++properties; | |
| 15587 } | |
| 15588 } | |
| 15589 RightTrimFixedArray<FROM_MUTATOR>(heap, storage, length - properties); | |
| 15590 } | 15575 } |
| 15591 return storage; | |
| 15592 } | 15576 } |
| 15593 | 15577 |
| 15594 | 15578 |
| 15595 template<typename Shape, typename Key> | 15579 template<typename Shape, typename Key> |
| 15596 void Dictionary<Shape, Key>::CopyKeysTo( | 15580 void Dictionary<Shape, Key>::CopyKeysTo( |
| 15597 FixedArray* storage, | 15581 FixedArray* storage, |
| 15598 int index, | 15582 int index, |
| 15599 PropertyAttributes filter, | 15583 PropertyAttributes filter, |
| 15600 typename Dictionary<Shape, Key>::SortMode sort_mode) { | 15584 typename Dictionary<Shape, Key>::SortMode sort_mode) { |
| 15601 ASSERT(storage->length() >= NumberOfElementsFilterAttributes(filter)); | 15585 ASSERT(storage->length() >= NumberOfElementsFilterAttributes(filter)); |
| (...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 15717 if (IsKey(k)) { | 15701 if (IsKey(k)) { |
| 15718 Object* value = ValueAt(i); | 15702 Object* value = ValueAt(i); |
| 15719 Name* key; | 15703 Name* key; |
| 15720 if (k->IsSymbol()) { | 15704 if (k->IsSymbol()) { |
| 15721 key = Symbol::cast(k); | 15705 key = Symbol::cast(k); |
| 15722 } else { | 15706 } else { |
| 15723 // Ensure the key is a unique name before writing into the | 15707 // Ensure the key is a unique name before writing into the |
| 15724 // instance descriptor. | 15708 // instance descriptor. |
| 15725 MaybeObject* maybe_key = heap->InternalizeString(String::cast(k)); | 15709 MaybeObject* maybe_key = heap->InternalizeString(String::cast(k)); |
| 15726 if (!maybe_key->To(&key)) return maybe_key; | 15710 if (!maybe_key->To(&key)) return maybe_key; |
| 15727 if (key->Equals(heap->empty_string())) return this; | |
| 15728 } | 15711 } |
| 15729 | 15712 |
| 15730 PropertyDetails details = DetailsAt(i); | 15713 PropertyDetails details = DetailsAt(i); |
| 15731 int enumeration_index = details.dictionary_index(); | 15714 int enumeration_index = details.dictionary_index(); |
| 15732 PropertyType type = details.type(); | 15715 PropertyType type = details.type(); |
| 15733 | 15716 |
| 15734 if (value->IsJSFunction()) { | 15717 if (value->IsJSFunction()) { |
| 15735 ConstantDescriptor d(key, value, details.attributes()); | 15718 ConstantDescriptor d(key, value, details.attributes()); |
| 15736 descriptors->Set(enumeration_index - 1, &d, witness); | 15719 descriptors->Set(enumeration_index - 1, &d, witness); |
| 15737 } else if (type == NORMAL) { | 15720 } else if (type == NORMAL) { |
| (...skipping 759 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 16497 #define ERROR_MESSAGES_TEXTS(C, T) T, | 16480 #define ERROR_MESSAGES_TEXTS(C, T) T, |
| 16498 static const char* error_messages_[] = { | 16481 static const char* error_messages_[] = { |
| 16499 ERROR_MESSAGES_LIST(ERROR_MESSAGES_TEXTS) | 16482 ERROR_MESSAGES_LIST(ERROR_MESSAGES_TEXTS) |
| 16500 }; | 16483 }; |
| 16501 #undef ERROR_MESSAGES_TEXTS | 16484 #undef ERROR_MESSAGES_TEXTS |
| 16502 return error_messages_[reason]; | 16485 return error_messages_[reason]; |
| 16503 } | 16486 } |
| 16504 | 16487 |
| 16505 | 16488 |
| 16506 } } // namespace v8::internal | 16489 } } // namespace v8::internal |
| OLD | NEW |