| 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 350 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 361 // TODO(rossberg): Handling symbols in the API requires changing the API, | 361 // TODO(rossberg): Handling symbols in the API requires changing the API, |
| 362 // so we do not support it for now. | 362 // so we do not support it for now. |
| 363 if (name->IsSymbol()) return isolate->heap()->undefined_value(); | 363 if (name->IsSymbol()) return isolate->heap()->undefined_value(); |
| 364 if (structure->IsDeclaredAccessorInfo()) { | 364 if (structure->IsDeclaredAccessorInfo()) { |
| 365 return GetDeclaredAccessorProperty(receiver, | 365 return GetDeclaredAccessorProperty(receiver, |
| 366 DeclaredAccessorInfo::cast(structure), | 366 DeclaredAccessorInfo::cast(structure), |
| 367 isolate); | 367 isolate); |
| 368 } | 368 } |
| 369 ExecutableAccessorInfo* data = ExecutableAccessorInfo::cast(structure); | 369 ExecutableAccessorInfo* data = ExecutableAccessorInfo::cast(structure); |
| 370 Object* fun_obj = data->getter(); | 370 Object* fun_obj = data->getter(); |
| 371 v8::AccessorGetter call_fun = v8::ToCData<v8::AccessorGetter>(fun_obj); | 371 v8::AccessorGetterCallback call_fun = |
| 372 v8::ToCData<v8::AccessorGetterCallback>(fun_obj); |
| 372 if (call_fun == NULL) return isolate->heap()->undefined_value(); | 373 if (call_fun == NULL) return isolate->heap()->undefined_value(); |
| 373 HandleScope scope(isolate); | 374 HandleScope scope(isolate); |
| 374 JSObject* self = JSObject::cast(receiver); | 375 JSObject* self = JSObject::cast(receiver); |
| 375 Handle<String> key(String::cast(name)); | 376 Handle<String> key(String::cast(name)); |
| 376 LOG(isolate, ApiNamedPropertyAccess("load", self, name)); | 377 LOG(isolate, ApiNamedPropertyAccess("load", self, name)); |
| 377 PropertyCallbackArguments args(isolate, data->data(), self, this); | 378 PropertyCallbackArguments args(isolate, data->data(), self, this); |
| 378 v8::Handle<v8::Value> result = | 379 v8::Handle<v8::Value> result = |
| 379 args.Call(call_fun, v8::Utils::ToLocal(key)); | 380 args.Call(call_fun, v8::Utils::ToLocal(key)); |
| 380 RETURN_IF_SCHEDULED_EXCEPTION(isolate); | 381 RETURN_IF_SCHEDULED_EXCEPTION(isolate); |
| 381 if (result.IsEmpty()) { | 382 if (result.IsEmpty()) { |
| (...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 506 case CALLBACKS: { | 507 case CALLBACKS: { |
| 507 // Only allow API accessors. | 508 // Only allow API accessors. |
| 508 Object* obj = result->GetCallbackObject(); | 509 Object* obj = result->GetCallbackObject(); |
| 509 if (obj->IsAccessorInfo()) { | 510 if (obj->IsAccessorInfo()) { |
| 510 AccessorInfo* info = AccessorInfo::cast(obj); | 511 AccessorInfo* info = AccessorInfo::cast(obj); |
| 511 if (info->all_can_read()) { | 512 if (info->all_can_read()) { |
| 512 *attributes = result->GetAttributes(); | 513 *attributes = result->GetAttributes(); |
| 513 return result->holder()->GetPropertyWithCallback( | 514 return result->holder()->GetPropertyWithCallback( |
| 514 receiver, result->GetCallbackObject(), name); | 515 receiver, result->GetCallbackObject(), name); |
| 515 } | 516 } |
| 517 } else if (obj->IsAccessorPair()) { |
| 518 AccessorPair* pair = AccessorPair::cast(obj); |
| 519 if (pair->all_can_read()) { |
| 520 return result->holder()->GetPropertyWithCallback( |
| 521 receiver, result->GetCallbackObject(), name); |
| 522 } |
| 516 } | 523 } |
| 517 break; | 524 break; |
| 518 } | 525 } |
| 519 case NORMAL: | 526 case NORMAL: |
| 520 case FIELD: | 527 case FIELD: |
| 521 case CONSTANT: { | 528 case CONSTANT: { |
| 522 // Search ALL_CAN_READ accessors in prototype chain. | 529 // Search ALL_CAN_READ accessors in prototype chain. |
| 523 LookupResult r(GetIsolate()); | 530 LookupResult r(GetIsolate()); |
| 524 result->holder()->LookupRealNamedPropertyInPrototypes(name, &r); | 531 result->holder()->LookupRealNamedPropertyInPrototypes(name, &r); |
| 525 if (r.IsProperty()) { | 532 if (r.IsProperty()) { |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 566 if (result->IsProperty()) { | 573 if (result->IsProperty()) { |
| 567 switch (result->type()) { | 574 switch (result->type()) { |
| 568 case CALLBACKS: { | 575 case CALLBACKS: { |
| 569 // Only allow API accessors. | 576 // Only allow API accessors. |
| 570 Object* obj = result->GetCallbackObject(); | 577 Object* obj = result->GetCallbackObject(); |
| 571 if (obj->IsAccessorInfo()) { | 578 if (obj->IsAccessorInfo()) { |
| 572 AccessorInfo* info = AccessorInfo::cast(obj); | 579 AccessorInfo* info = AccessorInfo::cast(obj); |
| 573 if (info->all_can_read()) { | 580 if (info->all_can_read()) { |
| 574 return result->GetAttributes(); | 581 return result->GetAttributes(); |
| 575 } | 582 } |
| 583 } else if (obj->IsAccessorPair()) { |
| 584 AccessorPair* pair = AccessorPair::cast(obj); |
| 585 if (pair->all_can_read()) { |
| 586 return result->GetAttributes(); |
| 587 } |
| 576 } | 588 } |
| 577 break; | 589 break; |
| 578 } | 590 } |
| 579 | 591 |
| 580 case NORMAL: | 592 case NORMAL: |
| 581 case FIELD: | 593 case FIELD: |
| 582 case CONSTANT: { | 594 case CONSTANT: { |
| 583 if (!continue_search) break; | 595 if (!continue_search) break; |
| 584 // Search ALL_CAN_READ accessors in prototype chain. | 596 // Search ALL_CAN_READ accessors in prototype chain. |
| 585 LookupResult r(GetIsolate()); | 597 LookupResult r(GetIsolate()); |
| (...skipping 857 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1443 PrintF(file, " from "); | 1455 PrintF(file, " from "); |
| 1444 from_elements->ShortPrint(file); | 1456 from_elements->ShortPrint(file); |
| 1445 PrintF(file, " to "); | 1457 PrintF(file, " to "); |
| 1446 to_elements->ShortPrint(file); | 1458 to_elements->ShortPrint(file); |
| 1447 PrintF(file, "\n"); | 1459 PrintF(file, "\n"); |
| 1448 } | 1460 } |
| 1449 } | 1461 } |
| 1450 | 1462 |
| 1451 | 1463 |
| 1452 void Map::PrintGeneralization(FILE* file, | 1464 void Map::PrintGeneralization(FILE* file, |
| 1465 const char* reason, |
| 1453 int modify_index, | 1466 int modify_index, |
| 1454 int split, | 1467 int split, |
| 1455 int descriptors, | 1468 int descriptors, |
| 1469 bool constant_to_field, |
| 1456 Representation old_representation, | 1470 Representation old_representation, |
| 1457 Representation new_representation) { | 1471 Representation new_representation) { |
| 1458 PrintF(file, "[generalizing "); | 1472 PrintF(file, "[generalizing "); |
| 1459 constructor_name()->PrintOn(file); | 1473 constructor_name()->PrintOn(file); |
| 1460 PrintF(file, "] "); | 1474 PrintF(file, "] "); |
| 1461 String::cast(instance_descriptors()->GetKey(modify_index))->PrintOn(file); | 1475 String::cast(instance_descriptors()->GetKey(modify_index))->PrintOn(file); |
| 1462 PrintF(file, ":%s->%s (+%i maps) [", | 1476 if (constant_to_field) { |
| 1463 old_representation.Mnemonic(), | 1477 PrintF(file, ":c->f"); |
| 1464 new_representation.Mnemonic(), | 1478 } else { |
| 1465 descriptors - split); | 1479 PrintF(file, ":%s->%s", |
| 1480 old_representation.Mnemonic(), |
| 1481 new_representation.Mnemonic()); |
| 1482 } |
| 1483 PrintF(file, " ("); |
| 1484 if (strlen(reason) > 0) { |
| 1485 PrintF(file, "%s", reason); |
| 1486 } else { |
| 1487 PrintF(file, "+%i maps", descriptors - split); |
| 1488 } |
| 1489 PrintF(file, ") ["); |
| 1466 JavaScriptFrame::PrintTop(GetIsolate(), file, false, true); | 1490 JavaScriptFrame::PrintTop(GetIsolate(), file, false, true); |
| 1467 PrintF(file, "]\n"); | 1491 PrintF(file, "]\n"); |
| 1468 } | 1492 } |
| 1469 | 1493 |
| 1470 | 1494 |
| 1471 void JSObject::PrintInstanceMigration(FILE* file, | 1495 void JSObject::PrintInstanceMigration(FILE* file, |
| 1472 Map* original_map, | 1496 Map* original_map, |
| 1473 Map* new_map) { | 1497 Map* new_map) { |
| 1474 PrintF(file, "[migrating "); | 1498 PrintF(file, "[migrating "); |
| 1475 map()->constructor_name()->PrintOn(file); | 1499 map()->constructor_name()->PrintOn(file); |
| (...skipping 421 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1897 } | 1921 } |
| 1898 } | 1922 } |
| 1899 return true; | 1923 return true; |
| 1900 } | 1924 } |
| 1901 | 1925 |
| 1902 | 1926 |
| 1903 MaybeObject* JSObject::AddFastProperty(Name* name, | 1927 MaybeObject* JSObject::AddFastProperty(Name* name, |
| 1904 Object* value, | 1928 Object* value, |
| 1905 PropertyAttributes attributes, | 1929 PropertyAttributes attributes, |
| 1906 StoreFromKeyed store_mode, | 1930 StoreFromKeyed store_mode, |
| 1907 ValueType value_type) { | 1931 ValueType value_type, |
| 1932 TransitionFlag flag) { |
| 1908 ASSERT(!IsJSGlobalProxy()); | 1933 ASSERT(!IsJSGlobalProxy()); |
| 1909 ASSERT(DescriptorArray::kNotFound == | 1934 ASSERT(DescriptorArray::kNotFound == |
| 1910 map()->instance_descriptors()->Search( | 1935 map()->instance_descriptors()->Search( |
| 1911 name, map()->NumberOfOwnDescriptors())); | 1936 name, map()->NumberOfOwnDescriptors())); |
| 1912 | 1937 |
| 1913 // Normalize the object if the name is an actual name (not the | 1938 // Normalize the object if the name is an actual name (not the |
| 1914 // hidden strings) and is not a real identifier. | 1939 // hidden strings) and is not a real identifier. |
| 1915 // Normalize the object if it will have too many fast properties. | 1940 // Normalize the object if it will have too many fast properties. |
| 1916 Isolate* isolate = GetHeap()->isolate(); | 1941 Isolate* isolate = GetHeap()->isolate(); |
| 1917 if ((!name->IsSymbol() && !IsIdentifier(isolate->unicode_cache(), name) | 1942 if ((!name->IsSymbol() && |
| 1918 && name != isolate->heap()->hidden_string()) || | 1943 !IsIdentifier(isolate->unicode_cache(), name) && |
| 1919 (map()->unused_property_fields() == 0 && | 1944 name != isolate->heap()->hidden_string()) || |
| 1920 TooManyFastProperties(properties()->length(), store_mode))) { | 1945 TooManyFastProperties(store_mode)) { |
| 1921 Object* obj; | 1946 MaybeObject* maybe_failure = |
| 1922 MaybeObject* maybe_obj = | |
| 1923 NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0); | 1947 NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0); |
| 1924 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 1948 if (maybe_failure->IsFailure()) return maybe_failure; |
| 1925 | |
| 1926 return AddSlowProperty(name, value, attributes); | 1949 return AddSlowProperty(name, value, attributes); |
| 1927 } | 1950 } |
| 1928 | 1951 |
| 1929 // Compute the new index for new field. | 1952 // Compute the new index for new field. |
| 1930 int index = map()->NextFreePropertyIndex(); | 1953 int index = map()->NextFreePropertyIndex(); |
| 1931 | 1954 |
| 1932 // Allocate new instance descriptors with (name, index) added | 1955 // Allocate new instance descriptors with (name, index) added |
| 1933 if (IsJSContextExtensionObject()) value_type = FORCE_TAGGED; | 1956 if (IsJSContextExtensionObject()) value_type = FORCE_TAGGED; |
| 1934 Representation representation = value->OptimalRepresentation(value_type); | 1957 Representation representation = value->OptimalRepresentation(value_type); |
| 1935 | 1958 |
| 1936 FieldDescriptor new_field(name, index, attributes, representation); | 1959 FieldDescriptor new_field(name, index, attributes, representation); |
| 1937 | 1960 |
| 1938 ASSERT(index < map()->inobject_properties() || | 1961 ASSERT(index < map()->inobject_properties() || |
| 1939 (index - map()->inobject_properties()) < properties()->length() || | 1962 (index - map()->inobject_properties()) < properties()->length() || |
| 1940 map()->unused_property_fields() == 0); | 1963 map()->unused_property_fields() == 0); |
| 1941 | 1964 |
| 1942 FixedArray* values = NULL; | 1965 FixedArray* values = NULL; |
| 1943 | 1966 |
| 1944 // TODO(verwaest): Merge with AddFastPropertyUsingMap. | 1967 // TODO(verwaest): Merge with AddFastPropertyUsingMap. |
| 1945 if (map()->unused_property_fields() == 0) { | 1968 if (map()->unused_property_fields() == 0) { |
| 1946 // Make room for the new value | 1969 // Make room for the new value |
| 1947 MaybeObject* maybe_values = | 1970 MaybeObject* maybe_values = |
| 1948 properties()->CopySize(properties()->length() + kFieldsAdded); | 1971 properties()->CopySize(properties()->length() + kFieldsAdded); |
| 1949 if (!maybe_values->To(&values)) return maybe_values; | 1972 if (!maybe_values->To(&values)) return maybe_values; |
| 1950 } | 1973 } |
| 1951 | 1974 |
| 1952 TransitionFlag flag = INSERT_TRANSITION; | |
| 1953 | |
| 1954 Heap* heap = isolate->heap(); | 1975 Heap* heap = isolate->heap(); |
| 1955 | 1976 |
| 1956 Object* storage; | 1977 Object* storage; |
| 1957 MaybeObject* maybe_storage = | 1978 MaybeObject* maybe_storage = |
| 1958 value->AllocateNewStorageFor(heap, representation); | 1979 value->AllocateNewStorageFor(heap, representation); |
| 1959 if (!maybe_storage->To(&storage)) return maybe_storage; | 1980 if (!maybe_storage->To(&storage)) return maybe_storage; |
| 1960 | 1981 |
| 1961 // Note that Map::CopyAddDescriptor has side-effects, the new map is already | 1982 // Note that Map::CopyAddDescriptor has side-effects, the new map is already |
| 1962 // inserted in the transition tree. No more allocations that might fail are | 1983 // inserted in the transition tree. No more allocations that might fail are |
| 1963 // allowed after this point. | 1984 // allowed after this point. |
| (...skipping 12 matching lines...) Expand all Loading... |
| 1976 set_map(new_map); | 1997 set_map(new_map); |
| 1977 | 1998 |
| 1978 FastPropertyAtPut(index, storage); | 1999 FastPropertyAtPut(index, storage); |
| 1979 return value; | 2000 return value; |
| 1980 } | 2001 } |
| 1981 | 2002 |
| 1982 | 2003 |
| 1983 MaybeObject* JSObject::AddConstantProperty( | 2004 MaybeObject* JSObject::AddConstantProperty( |
| 1984 Name* name, | 2005 Name* name, |
| 1985 Object* constant, | 2006 Object* constant, |
| 1986 PropertyAttributes attributes) { | 2007 PropertyAttributes attributes, |
| 2008 TransitionFlag initial_flag) { |
| 1987 // Allocate new instance descriptors with (name, constant) added | 2009 // Allocate new instance descriptors with (name, constant) added |
| 1988 ConstantDescriptor d(name, constant, attributes); | 2010 ConstantDescriptor d(name, constant, attributes); |
| 1989 | 2011 |
| 1990 TransitionFlag flag = | 2012 TransitionFlag flag = |
| 1991 // Do not add transitions to global objects. | 2013 // Do not add transitions to global objects. |
| 1992 (IsGlobalObject() || | 2014 (IsGlobalObject() || |
| 1993 // Don't add transitions to special properties with non-trivial | 2015 // Don't add transitions to special properties with non-trivial |
| 1994 // attributes. | 2016 // attributes. |
| 1995 attributes != NONE) | 2017 attributes != NONE) |
| 1996 ? OMIT_TRANSITION | 2018 ? OMIT_TRANSITION |
| 1997 : INSERT_TRANSITION; | 2019 : initial_flag; |
| 1998 | 2020 |
| 1999 Map* new_map; | 2021 Map* new_map; |
| 2000 MaybeObject* maybe_new_map = map()->CopyAddDescriptor(&d, flag); | 2022 MaybeObject* maybe_new_map = map()->CopyAddDescriptor(&d, flag); |
| 2001 if (!maybe_new_map->To(&new_map)) return maybe_new_map; | 2023 if (!maybe_new_map->To(&new_map)) return maybe_new_map; |
| 2002 | 2024 |
| 2003 set_map(new_map); | 2025 set_map(new_map); |
| 2004 return constant; | 2026 return constant; |
| 2005 } | 2027 } |
| 2006 | 2028 |
| 2007 | 2029 |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2047 } | 2069 } |
| 2048 | 2070 |
| 2049 | 2071 |
| 2050 MaybeObject* JSObject::AddProperty(Name* name, | 2072 MaybeObject* JSObject::AddProperty(Name* name, |
| 2051 Object* value, | 2073 Object* value, |
| 2052 PropertyAttributes attributes, | 2074 PropertyAttributes attributes, |
| 2053 StrictModeFlag strict_mode, | 2075 StrictModeFlag strict_mode, |
| 2054 JSReceiver::StoreFromKeyed store_mode, | 2076 JSReceiver::StoreFromKeyed store_mode, |
| 2055 ExtensibilityCheck extensibility_check, | 2077 ExtensibilityCheck extensibility_check, |
| 2056 ValueType value_type, | 2078 ValueType value_type, |
| 2057 StoreMode mode) { | 2079 StoreMode mode, |
| 2080 TransitionFlag transition_flag) { |
| 2058 ASSERT(!IsJSGlobalProxy()); | 2081 ASSERT(!IsJSGlobalProxy()); |
| 2059 Map* map_of_this = map(); | 2082 Map* map_of_this = map(); |
| 2060 Heap* heap = GetHeap(); | 2083 Heap* heap = GetHeap(); |
| 2061 Isolate* isolate = heap->isolate(); | 2084 Isolate* isolate = heap->isolate(); |
| 2062 MaybeObject* result; | 2085 MaybeObject* result; |
| 2063 if (extensibility_check == PERFORM_EXTENSIBILITY_CHECK && | 2086 if (extensibility_check == PERFORM_EXTENSIBILITY_CHECK && |
| 2064 !map_of_this->is_extensible()) { | 2087 !map_of_this->is_extensible()) { |
| 2065 if (strict_mode == kNonStrictMode) { | 2088 if (strict_mode == kNonStrictMode) { |
| 2066 return value; | 2089 return value; |
| 2067 } else { | 2090 } else { |
| 2068 Handle<Object> args[1] = {Handle<Name>(name)}; | 2091 Handle<Object> args[1] = {Handle<Name>(name)}; |
| 2069 return isolate->Throw( | 2092 return isolate->Throw( |
| 2070 *isolate->factory()->NewTypeError("object_not_extensible", | 2093 *isolate->factory()->NewTypeError("object_not_extensible", |
| 2071 HandleVector(args, 1))); | 2094 HandleVector(args, 1))); |
| 2072 } | 2095 } |
| 2073 } | 2096 } |
| 2074 | 2097 |
| 2075 if (HasFastProperties()) { | 2098 if (HasFastProperties()) { |
| 2076 // Ensure the descriptor array does not get too big. | 2099 // Ensure the descriptor array does not get too big. |
| 2077 if (map_of_this->NumberOfOwnDescriptors() < | 2100 if (map_of_this->NumberOfOwnDescriptors() < |
| 2078 DescriptorArray::kMaxNumberOfDescriptors) { | 2101 DescriptorArray::kMaxNumberOfDescriptors) { |
| 2079 // TODO(verwaest): Support other constants. | 2102 // TODO(verwaest): Support other constants. |
| 2080 // if (mode == ALLOW_AS_CONSTANT && | 2103 // if (mode == ALLOW_AS_CONSTANT && |
| 2081 // !value->IsTheHole() && | 2104 // !value->IsTheHole() && |
| 2082 // !value->IsConsString()) { | 2105 // !value->IsConsString()) { |
| 2083 if (value->IsJSFunction()) { | 2106 if (value->IsJSFunction()) { |
| 2084 result = AddConstantProperty(name, value, attributes); | 2107 result = AddConstantProperty(name, value, attributes, transition_flag); |
| 2085 } else { | 2108 } else { |
| 2086 result = AddFastProperty( | 2109 result = AddFastProperty( |
| 2087 name, value, attributes, store_mode, value_type); | 2110 name, value, attributes, store_mode, value_type, transition_flag); |
| 2088 } | 2111 } |
| 2089 } else { | 2112 } else { |
| 2090 // Normalize the object to prevent very large instance descriptors. | 2113 // Normalize the object to prevent very large instance descriptors. |
| 2091 // This eliminates unwanted N^2 allocation and lookup behavior. | 2114 // This eliminates unwanted N^2 allocation and lookup behavior. |
| 2092 Object* obj; | 2115 Object* obj; |
| 2093 MaybeObject* maybe = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0); | 2116 MaybeObject* maybe = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0); |
| 2094 if (!maybe->To(&obj)) return maybe; | 2117 if (!maybe->To(&obj)) return maybe; |
| 2095 result = AddSlowProperty(name, value, attributes); | 2118 result = AddSlowProperty(name, value, attributes); |
| 2096 } | 2119 } |
| 2097 } else { | 2120 } else { |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2144 ASSERT(!threw); | 2167 ASSERT(!threw); |
| 2145 isolate->set_observer_delivery_pending(false); | 2168 isolate->set_observer_delivery_pending(false); |
| 2146 } | 2169 } |
| 2147 | 2170 |
| 2148 | 2171 |
| 2149 MaybeObject* JSObject::SetPropertyPostInterceptor( | 2172 MaybeObject* JSObject::SetPropertyPostInterceptor( |
| 2150 Name* name, | 2173 Name* name, |
| 2151 Object* value, | 2174 Object* value, |
| 2152 PropertyAttributes attributes, | 2175 PropertyAttributes attributes, |
| 2153 StrictModeFlag strict_mode, | 2176 StrictModeFlag strict_mode, |
| 2154 ExtensibilityCheck extensibility_check, | |
| 2155 StoreMode mode) { | 2177 StoreMode mode) { |
| 2156 // Check local property, ignore interceptor. | 2178 // Check local property, ignore interceptor. |
| 2157 LookupResult result(GetIsolate()); | 2179 LookupResult result(GetIsolate()); |
| 2158 LocalLookupRealNamedProperty(name, &result); | 2180 LocalLookupRealNamedProperty(name, &result); |
| 2159 if (!result.IsFound()) map()->LookupTransition(this, name, &result); | 2181 if (!result.IsFound()) map()->LookupTransition(this, name, &result); |
| 2160 if (result.IsFound()) { | 2182 if (result.IsFound()) { |
| 2161 // An existing property or a map transition was found. Use set property to | 2183 // An existing property or a map transition was found. Use set property to |
| 2162 // handle all these cases. | 2184 // handle all these cases. |
| 2163 return SetProperty(&result, name, value, attributes, strict_mode); | 2185 return SetProperty(&result, name, value, attributes, strict_mode); |
| 2164 } | 2186 } |
| 2165 bool done = false; | 2187 bool done = false; |
| 2166 MaybeObject* result_object; | 2188 MaybeObject* result_object = |
| 2167 result_object = | |
| 2168 SetPropertyViaPrototypes(name, value, attributes, strict_mode, &done); | 2189 SetPropertyViaPrototypes(name, value, attributes, strict_mode, &done); |
| 2169 if (done) return result_object; | 2190 if (done) return result_object; |
| 2170 // Add a new real property. | 2191 // Add a new real property. |
| 2171 return AddProperty(name, value, attributes, strict_mode, | 2192 return AddProperty(name, value, attributes, strict_mode, |
| 2172 MAY_BE_STORE_FROM_KEYED, extensibility_check, | 2193 MAY_BE_STORE_FROM_KEYED, PERFORM_EXTENSIBILITY_CHECK, |
| 2173 OPTIMAL_REPRESENTATION, mode); | 2194 OPTIMAL_REPRESENTATION, mode); |
| 2174 } | 2195 } |
| 2175 | 2196 |
| 2176 | 2197 |
| 2177 MaybeObject* JSObject::ReplaceSlowProperty(Name* name, | 2198 MaybeObject* JSObject::ReplaceSlowProperty(Name* name, |
| 2178 Object* value, | 2199 Object* value, |
| 2179 PropertyAttributes attributes) { | 2200 PropertyAttributes attributes) { |
| 2180 NameDictionary* dictionary = property_dictionary(); | 2201 NameDictionary* dictionary = property_dictionary(); |
| 2181 int old_index = dictionary->FindEntry(name); | 2202 int old_index = dictionary->FindEntry(name); |
| 2182 int new_enumeration_index = 0; // 0 means "Use the next available index." | 2203 int new_enumeration_index = 0; // 0 means "Use the next available index." |
| 2183 if (old_index != -1) { | 2204 if (old_index != -1) { |
| 2184 // All calls to ReplaceSlowProperty have had all transitions removed. | 2205 // All calls to ReplaceSlowProperty have had all transitions removed. |
| 2185 new_enumeration_index = dictionary->DetailsAt(old_index).dictionary_index(); | 2206 new_enumeration_index = dictionary->DetailsAt(old_index).dictionary_index(); |
| 2186 } | 2207 } |
| 2187 | 2208 |
| 2188 PropertyDetails new_details(attributes, NORMAL, new_enumeration_index); | 2209 PropertyDetails new_details(attributes, NORMAL, new_enumeration_index); |
| 2189 return SetNormalizedProperty(name, value, new_details); | 2210 return SetNormalizedProperty(name, value, new_details); |
| 2190 } | 2211 } |
| 2191 | 2212 |
| 2192 | 2213 |
| 2193 MaybeObject* JSObject::ConvertTransitionToMapTransition( | |
| 2194 int transition_index, | |
| 2195 Name* name, | |
| 2196 Object* new_value, | |
| 2197 PropertyAttributes attributes) { | |
| 2198 Map* old_map = map(); | |
| 2199 Map* old_target = old_map->GetTransition(transition_index); | |
| 2200 Object* result; | |
| 2201 | |
| 2202 MaybeObject* maybe_result = ConvertDescriptorToField( | |
| 2203 name, new_value, attributes, OMIT_TRANSITION_KEEP_REPRESENTATIONS); | |
| 2204 if (!maybe_result->To(&result)) return maybe_result; | |
| 2205 | |
| 2206 if (!HasFastProperties()) return result; | |
| 2207 | |
| 2208 // This method should only be used to convert existing transitions. | |
| 2209 Map* new_map = map(); | |
| 2210 | |
| 2211 // TODO(verwaest): From here on we lose existing map transitions, causing | |
| 2212 // invalid back pointers. This will change once we can store multiple | |
| 2213 // transitions with the same key. | |
| 2214 bool owned_descriptors = old_map->owns_descriptors(); | |
| 2215 if (owned_descriptors || | |
| 2216 old_target->instance_descriptors() == old_map->instance_descriptors()) { | |
| 2217 // Since the conversion above generated a new fast map with an additional | |
| 2218 // property which can be shared as well, install this descriptor pointer | |
| 2219 // along the entire chain of smaller maps. | |
| 2220 Map* map; | |
| 2221 DescriptorArray* new_descriptors = new_map->instance_descriptors(); | |
| 2222 DescriptorArray* old_descriptors = old_map->instance_descriptors(); | |
| 2223 for (Object* current = old_map; | |
| 2224 !current->IsUndefined(); | |
| 2225 current = map->GetBackPointer()) { | |
| 2226 map = Map::cast(current); | |
| 2227 if (map->instance_descriptors() != old_descriptors) break; | |
| 2228 map->SetEnumLength(Map::kInvalidEnumCache); | |
| 2229 map->set_instance_descriptors(new_descriptors); | |
| 2230 } | |
| 2231 old_map->set_owns_descriptors(false); | |
| 2232 } | |
| 2233 | |
| 2234 old_target->DeprecateTransitionTree(); | |
| 2235 | |
| 2236 old_map->SetTransition(transition_index, new_map); | |
| 2237 new_map->SetBackPointer(old_map); | |
| 2238 return result; | |
| 2239 } | |
| 2240 | |
| 2241 | |
| 2242 MaybeObject* JSObject::ConvertDescriptorToField(Name* name, | |
| 2243 Object* new_value, | |
| 2244 PropertyAttributes attributes, | |
| 2245 TransitionFlag flag) { | |
| 2246 if (map()->unused_property_fields() == 0 && | |
| 2247 TooManyFastProperties(properties()->length(), MAY_BE_STORE_FROM_KEYED)) { | |
| 2248 Object* obj; | |
| 2249 MaybeObject* maybe_obj = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0); | |
| 2250 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | |
| 2251 return ReplaceSlowProperty(name, new_value, attributes); | |
| 2252 } | |
| 2253 | |
| 2254 Representation representation = IsJSContextExtensionObject() | |
| 2255 ? Representation::Tagged() : new_value->OptimalRepresentation(); | |
| 2256 int index = map()->NextFreePropertyIndex(); | |
| 2257 FieldDescriptor new_field(name, index, attributes, representation); | |
| 2258 | |
| 2259 // Make a new map for the object. | |
| 2260 Map* new_map; | |
| 2261 MaybeObject* maybe_new_map = map()->CopyInsertDescriptor(&new_field, flag); | |
| 2262 if (!maybe_new_map->To(&new_map)) return maybe_new_map; | |
| 2263 | |
| 2264 // Make new properties array if necessary. | |
| 2265 FixedArray* new_properties = NULL; | |
| 2266 int new_unused_property_fields = map()->unused_property_fields() - 1; | |
| 2267 if (map()->unused_property_fields() == 0) { | |
| 2268 new_unused_property_fields = kFieldsAdded - 1; | |
| 2269 MaybeObject* maybe_new_properties = | |
| 2270 properties()->CopySize(properties()->length() + kFieldsAdded); | |
| 2271 if (!maybe_new_properties->To(&new_properties)) return maybe_new_properties; | |
| 2272 } | |
| 2273 | |
| 2274 Heap* heap = GetHeap(); | |
| 2275 Object* storage; | |
| 2276 MaybeObject* maybe_storage = | |
| 2277 new_value->AllocateNewStorageFor(heap, representation); | |
| 2278 if (!maybe_storage->To(&storage)) return maybe_storage; | |
| 2279 | |
| 2280 // Update pointers to commit changes. | |
| 2281 // Object points to the new map. | |
| 2282 new_map->set_unused_property_fields(new_unused_property_fields); | |
| 2283 set_map(new_map); | |
| 2284 if (new_properties != NULL) { | |
| 2285 set_properties(new_properties); | |
| 2286 } | |
| 2287 FastPropertyAtPut(index, storage); | |
| 2288 return new_value; | |
| 2289 } | |
| 2290 | |
| 2291 | |
| 2292 const char* Representation::Mnemonic() const { | 2214 const char* Representation::Mnemonic() const { |
| 2293 switch (kind_) { | 2215 switch (kind_) { |
| 2294 case kNone: return "v"; | 2216 case kNone: return "v"; |
| 2295 case kTagged: return "t"; | 2217 case kTagged: return "t"; |
| 2296 case kSmi: return "s"; | 2218 case kSmi: return "s"; |
| 2297 case kDouble: return "d"; | 2219 case kDouble: return "d"; |
| 2298 case kInteger32: return "i"; | 2220 case kInteger32: return "i"; |
| 2299 case kHeapObject: return "h"; | 2221 case kHeapObject: return "h"; |
| 2300 case kExternal: return "x"; | 2222 case kExternal: return "x"; |
| 2301 default: | 2223 default: |
| (...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2428 if (!maybe_array->To(&array)) return maybe_array; | 2350 if (!maybe_array->To(&array)) return maybe_array; |
| 2429 | 2351 |
| 2430 DescriptorArray* old_descriptors = old_map->instance_descriptors(); | 2352 DescriptorArray* old_descriptors = old_map->instance_descriptors(); |
| 2431 DescriptorArray* new_descriptors = new_map->instance_descriptors(); | 2353 DescriptorArray* new_descriptors = new_map->instance_descriptors(); |
| 2432 int descriptors = new_map->NumberOfOwnDescriptors(); | 2354 int descriptors = new_map->NumberOfOwnDescriptors(); |
| 2433 | 2355 |
| 2434 for (int i = 0; i < descriptors; i++) { | 2356 for (int i = 0; i < descriptors; i++) { |
| 2435 PropertyDetails details = new_descriptors->GetDetails(i); | 2357 PropertyDetails details = new_descriptors->GetDetails(i); |
| 2436 if (details.type() != FIELD) continue; | 2358 if (details.type() != FIELD) continue; |
| 2437 PropertyDetails old_details = old_descriptors->GetDetails(i); | 2359 PropertyDetails old_details = old_descriptors->GetDetails(i); |
| 2360 if (old_details.type() == CALLBACKS) { |
| 2361 ASSERT(details.representation().IsTagged()); |
| 2362 continue; |
| 2363 } |
| 2438 ASSERT(old_details.type() == CONSTANT || | 2364 ASSERT(old_details.type() == CONSTANT || |
| 2439 old_details.type() == FIELD); | 2365 old_details.type() == FIELD); |
| 2440 Object* value = old_details.type() == CONSTANT | 2366 Object* value = old_details.type() == CONSTANT |
| 2441 ? old_descriptors->GetValue(i) | 2367 ? old_descriptors->GetValue(i) |
| 2442 : RawFastPropertyAt(old_descriptors->GetFieldIndex(i)); | 2368 : RawFastPropertyAt(old_descriptors->GetFieldIndex(i)); |
| 2443 if (FLAG_track_double_fields && | 2369 if (FLAG_track_double_fields && |
| 2444 !old_details.representation().IsDouble() && | 2370 !old_details.representation().IsDouble() && |
| 2445 details.representation().IsDouble()) { | 2371 details.representation().IsDouble()) { |
| 2446 if (old_details.representation().IsNone()) value = Smi::FromInt(0); | 2372 if (old_details.representation().IsNone()) value = Smi::FromInt(0); |
| 2447 // Objects must be allocated in the old object space, since the | 2373 // Objects must be allocated in the old object space, since the |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2484 } | 2410 } |
| 2485 | 2411 |
| 2486 set_map(new_map); | 2412 set_map(new_map); |
| 2487 | 2413 |
| 2488 return this; | 2414 return this; |
| 2489 } | 2415 } |
| 2490 | 2416 |
| 2491 | 2417 |
| 2492 MaybeObject* JSObject::GeneralizeFieldRepresentation( | 2418 MaybeObject* JSObject::GeneralizeFieldRepresentation( |
| 2493 int modify_index, | 2419 int modify_index, |
| 2494 Representation new_representation) { | 2420 Representation new_representation, |
| 2421 StoreMode store_mode) { |
| 2495 Map* new_map; | 2422 Map* new_map; |
| 2496 MaybeObject* maybe_new_map = | 2423 MaybeObject* maybe_new_map = map()->GeneralizeRepresentation( |
| 2497 map()->GeneralizeRepresentation(modify_index, new_representation); | 2424 modify_index, new_representation, store_mode); |
| 2498 if (!maybe_new_map->To(&new_map)) return maybe_new_map; | 2425 if (!maybe_new_map->To(&new_map)) return maybe_new_map; |
| 2499 if (map() == new_map) return this; | 2426 if (map() == new_map) return this; |
| 2500 | 2427 |
| 2501 return MigrateToMap(new_map); | 2428 return MigrateToMap(new_map); |
| 2502 } | 2429 } |
| 2503 | 2430 |
| 2504 | 2431 |
| 2505 int Map::NumberOfFields() { | 2432 int Map::NumberOfFields() { |
| 2506 DescriptorArray* descriptors = instance_descriptors(); | 2433 DescriptorArray* descriptors = instance_descriptors(); |
| 2507 int result = 0; | 2434 int result = 0; |
| 2508 for (int i = 0; i < NumberOfOwnDescriptors(); i++) { | 2435 for (int i = 0; i < NumberOfOwnDescriptors(); i++) { |
| 2509 if (descriptors->GetDetails(i).type() == FIELD) result++; | 2436 if (descriptors->GetDetails(i).type() == FIELD) result++; |
| 2510 } | 2437 } |
| 2511 return result; | 2438 return result; |
| 2512 } | 2439 } |
| 2513 | 2440 |
| 2514 | 2441 |
| 2515 MaybeObject* Map::CopyGeneralizeAllRepresentations() { | 2442 MaybeObject* Map::CopyGeneralizeAllRepresentations( |
| 2443 int modify_index, |
| 2444 StoreMode store_mode, |
| 2445 PropertyAttributes attributes, |
| 2446 const char* reason) { |
| 2516 Map* new_map; | 2447 Map* new_map; |
| 2517 MaybeObject* maybe_map = this->Copy(); | 2448 MaybeObject* maybe_map = this->Copy(); |
| 2518 if (!maybe_map->To(&new_map)) return maybe_map; | 2449 if (!maybe_map->To(&new_map)) return maybe_map; |
| 2519 | 2450 |
| 2520 new_map->instance_descriptors()->InitializeRepresentations( | 2451 DescriptorArray* descriptors = new_map->instance_descriptors(); |
| 2521 Representation::Tagged()); | 2452 descriptors->InitializeRepresentations(Representation::Tagged()); |
| 2453 |
| 2454 // Unless the instance is being migrated, ensure that modify_index is a field. |
| 2455 PropertyDetails details = descriptors->GetDetails(modify_index); |
| 2456 if (store_mode == FORCE_FIELD && details.type() != FIELD) { |
| 2457 FieldDescriptor d(descriptors->GetKey(modify_index), |
| 2458 new_map->NumberOfFields(), |
| 2459 attributes, |
| 2460 Representation::Tagged()); |
| 2461 d.SetSortedKeyIndex(details.pointer()); |
| 2462 descriptors->Set(modify_index, &d); |
| 2463 int unused_property_fields = new_map->unused_property_fields() - 1; |
| 2464 if (unused_property_fields < 0) { |
| 2465 unused_property_fields += JSObject::kFieldsAdded; |
| 2466 } |
| 2467 new_map->set_unused_property_fields(unused_property_fields); |
| 2468 } |
| 2469 |
| 2522 if (FLAG_trace_generalization) { | 2470 if (FLAG_trace_generalization) { |
| 2523 PrintF("failed generalization %p -> %p\n", | 2471 PrintGeneralization(stdout, reason, modify_index, |
| 2524 static_cast<void*>(this), static_cast<void*>(new_map)); | 2472 new_map->NumberOfOwnDescriptors(), |
| 2473 new_map->NumberOfOwnDescriptors(), |
| 2474 details.type() == CONSTANT && store_mode == FORCE_FIELD, |
| 2475 Representation::Tagged(), Representation::Tagged()); |
| 2525 } | 2476 } |
| 2526 return new_map; | 2477 return new_map; |
| 2527 } | 2478 } |
| 2528 | 2479 |
| 2529 | 2480 |
| 2530 void Map::DeprecateTransitionTree() { | 2481 void Map::DeprecateTransitionTree() { |
| 2531 if (!FLAG_track_fields) return; | 2482 if (!FLAG_track_fields) return; |
| 2532 if (is_deprecated()) return; | 2483 if (is_deprecated()) return; |
| 2533 if (HasTransitionArray()) { | 2484 if (HasTransitionArray()) { |
| 2534 TransitionArray* transitions = this->transitions(); | 2485 TransitionArray* transitions = this->transitions(); |
| (...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2659 // walk the transition tree. | 2610 // walk the transition tree. |
| 2660 // - Merge/generalize the descriptor array of the current map and |updated|. | 2611 // - Merge/generalize the descriptor array of the current map and |updated|. |
| 2661 // - Generalize the |modify_index| descriptor using |new_representation|. | 2612 // - Generalize the |modify_index| descriptor using |new_representation|. |
| 2662 // - Walk the tree again starting from the root towards |updated|. Stop at | 2613 // - Walk the tree again starting from the root towards |updated|. Stop at |
| 2663 // |split_map|, the first map who's descriptor array does not match the merged | 2614 // |split_map|, the first map who's descriptor array does not match the merged |
| 2664 // descriptor array. | 2615 // descriptor array. |
| 2665 // - If |updated| == |split_map|, |updated| is in the expected state. Return it. | 2616 // - If |updated| == |split_map|, |updated| is in the expected state. Return it. |
| 2666 // - Otherwise, invalidate the outdated transition target from |updated|, and | 2617 // - Otherwise, invalidate the outdated transition target from |updated|, and |
| 2667 // replace its transition tree with a new branch for the updated descriptors. | 2618 // replace its transition tree with a new branch for the updated descriptors. |
| 2668 MaybeObject* Map::GeneralizeRepresentation(int modify_index, | 2619 MaybeObject* Map::GeneralizeRepresentation(int modify_index, |
| 2669 Representation new_representation) { | 2620 Representation new_representation, |
| 2621 StoreMode store_mode) { |
| 2670 Map* old_map = this; | 2622 Map* old_map = this; |
| 2671 DescriptorArray* old_descriptors = old_map->instance_descriptors(); | 2623 DescriptorArray* old_descriptors = old_map->instance_descriptors(); |
| 2672 Representation old_representation = | 2624 PropertyDetails old_details = old_descriptors->GetDetails(modify_index); |
| 2673 old_descriptors->GetDetails(modify_index).representation(); | 2625 Representation old_representation = old_details.representation(); |
| 2674 | 2626 |
| 2675 // It's fine to transition from None to anything but double without any | 2627 // It's fine to transition from None to anything but double without any |
| 2676 // modification to the object, because the default uninitialized value for | 2628 // modification to the object, because the default uninitialized value for |
| 2677 // representation None can be overwritten by both smi and tagged values. | 2629 // representation None can be overwritten by both smi and tagged values. |
| 2678 // Doubles, however, would require a box allocation. | 2630 // Doubles, however, would require a box allocation. |
| 2679 if (old_representation.IsNone() && | 2631 if (old_representation.IsNone() && |
| 2680 !new_representation.IsNone() && | 2632 !new_representation.IsNone() && |
| 2681 !new_representation.IsDouble()) { | 2633 !new_representation.IsDouble()) { |
| 2682 old_descriptors->SetRepresentation(modify_index, new_representation); | 2634 old_descriptors->SetRepresentation(modify_index, new_representation); |
| 2683 return old_map; | 2635 return old_map; |
| 2684 } | 2636 } |
| 2685 | 2637 |
| 2686 int descriptors = old_map->NumberOfOwnDescriptors(); | 2638 int descriptors = old_map->NumberOfOwnDescriptors(); |
| 2687 Map* root_map = old_map->FindRootMap(); | 2639 Map* root_map = old_map->FindRootMap(); |
| 2688 | 2640 |
| 2689 // Check the state of the root map. | 2641 // Check the state of the root map. |
| 2690 if (!old_map->EquivalentToForTransition(root_map)) { | 2642 if (!old_map->EquivalentToForTransition(root_map)) { |
| 2691 return CopyGeneralizeAllRepresentations(); | 2643 return CopyGeneralizeAllRepresentations( |
| 2644 modify_index, store_mode, old_details.attributes(), "not equivalent"); |
| 2692 } | 2645 } |
| 2693 | 2646 |
| 2694 int verbatim = root_map->NumberOfOwnDescriptors(); | 2647 int verbatim = root_map->NumberOfOwnDescriptors(); |
| 2695 | 2648 |
| 2649 if (store_mode != ALLOW_AS_CONSTANT && modify_index < verbatim) { |
| 2650 return CopyGeneralizeAllRepresentations( |
| 2651 modify_index, store_mode, |
| 2652 old_details.attributes(), "root modification"); |
| 2653 } |
| 2654 |
| 2696 Map* updated = root_map->FindUpdatedMap( | 2655 Map* updated = root_map->FindUpdatedMap( |
| 2697 verbatim, descriptors, old_descriptors); | 2656 verbatim, descriptors, old_descriptors); |
| 2698 if (updated == NULL) return CopyGeneralizeAllRepresentations(); | 2657 if (updated == NULL) { |
| 2658 return CopyGeneralizeAllRepresentations( |
| 2659 modify_index, store_mode, old_details.attributes(), "incompatible"); |
| 2660 } |
| 2699 | 2661 |
| 2700 DescriptorArray* updated_descriptors = updated->instance_descriptors(); | 2662 DescriptorArray* updated_descriptors = updated->instance_descriptors(); |
| 2701 | 2663 |
| 2702 int valid = updated->NumberOfOwnDescriptors(); | 2664 int valid = updated->NumberOfOwnDescriptors(); |
| 2665 |
| 2666 // Directly change the map if the target map is more general. Ensure that the |
| 2667 // target type of the modify_index is a FIELD, unless we are migrating. |
| 2703 if (updated_descriptors->IsMoreGeneralThan( | 2668 if (updated_descriptors->IsMoreGeneralThan( |
| 2704 verbatim, valid, descriptors, old_descriptors)) { | 2669 verbatim, valid, descriptors, old_descriptors) && |
| 2670 (store_mode == ALLOW_AS_CONSTANT || |
| 2671 updated_descriptors->GetDetails(modify_index).type() == FIELD)) { |
| 2705 Representation updated_representation = | 2672 Representation updated_representation = |
| 2706 updated_descriptors->GetDetails(modify_index).representation(); | 2673 updated_descriptors->GetDetails(modify_index).representation(); |
| 2707 if (new_representation.fits_into(updated_representation)) { | 2674 if (new_representation.fits_into(updated_representation)) return updated; |
| 2708 if (FLAG_trace_generalization && | |
| 2709 !(modify_index == 0 && new_representation.IsNone())) { | |
| 2710 PropertyDetails old_details = old_descriptors->GetDetails(modify_index); | |
| 2711 PrintGeneralization(stdout, modify_index, descriptors, descriptors, | |
| 2712 old_details.representation(), | |
| 2713 updated_representation); | |
| 2714 } | |
| 2715 return updated; | |
| 2716 } | |
| 2717 } | 2675 } |
| 2718 | 2676 |
| 2719 DescriptorArray* new_descriptors; | 2677 DescriptorArray* new_descriptors; |
| 2720 MaybeObject* maybe_descriptors = updated_descriptors->Merge( | 2678 MaybeObject* maybe_descriptors = updated_descriptors->Merge( |
| 2721 verbatim, valid, descriptors, old_descriptors); | 2679 verbatim, valid, descriptors, modify_index, store_mode, old_descriptors); |
| 2722 if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors; | 2680 if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors; |
| 2681 ASSERT(store_mode == ALLOW_AS_CONSTANT || |
| 2682 new_descriptors->GetDetails(modify_index).type() == FIELD); |
| 2723 | 2683 |
| 2724 old_representation = | 2684 old_representation = |
| 2725 new_descriptors->GetDetails(modify_index).representation(); | 2685 new_descriptors->GetDetails(modify_index).representation(); |
| 2726 Representation updated_representation = | 2686 Representation updated_representation = |
| 2727 new_representation.generalize(old_representation); | 2687 new_representation.generalize(old_representation); |
| 2728 if (!updated_representation.Equals(old_representation)) { | 2688 if (!updated_representation.Equals(old_representation)) { |
| 2729 new_descriptors->SetRepresentation(modify_index, updated_representation); | 2689 new_descriptors->SetRepresentation(modify_index, updated_representation); |
| 2730 } | 2690 } |
| 2731 | 2691 |
| 2732 Map* split_map = root_map->FindLastMatchMap( | 2692 Map* split_map = root_map->FindLastMatchMap( |
| 2733 verbatim, descriptors, new_descriptors); | 2693 verbatim, descriptors, new_descriptors); |
| 2734 | 2694 |
| 2735 int split_descriptors = split_map->NumberOfOwnDescriptors(); | 2695 int split_descriptors = split_map->NumberOfOwnDescriptors(); |
| 2736 // This is shadowed by |updated_descriptors| being more general than | 2696 // This is shadowed by |updated_descriptors| being more general than |
| 2737 // |old_descriptors|. | 2697 // |old_descriptors|. |
| 2738 ASSERT(descriptors != split_descriptors); | 2698 ASSERT(descriptors != split_descriptors); |
| 2739 | 2699 |
| 2740 int descriptor = split_descriptors; | 2700 int descriptor = split_descriptors; |
| 2741 split_map->DeprecateTarget( | 2701 split_map->DeprecateTarget( |
| 2742 old_descriptors->GetKey(descriptor), new_descriptors); | 2702 old_descriptors->GetKey(descriptor), new_descriptors); |
| 2743 | 2703 |
| 2744 if (FLAG_trace_generalization && | 2704 if (FLAG_trace_generalization) { |
| 2745 !(modify_index == 0 && new_representation.IsNone())) { | 2705 PrintGeneralization( |
| 2746 PrintGeneralization(stdout, modify_index, descriptor, descriptors, | 2706 stdout, "", modify_index, descriptor, descriptors, |
| 2747 old_representation, updated_representation); | 2707 old_descriptors->GetDetails(modify_index).type() == CONSTANT && |
| 2708 store_mode == FORCE_FIELD, |
| 2709 old_representation, updated_representation); |
| 2748 } | 2710 } |
| 2749 | 2711 |
| 2750 Map* new_map = split_map; | 2712 Map* new_map = split_map; |
| 2751 // Add missing transitions. | 2713 // Add missing transitions. |
| 2752 for (; descriptor < descriptors; descriptor++) { | 2714 for (; descriptor < descriptors; descriptor++) { |
| 2753 MaybeObject* maybe_map = new_map->CopyInstallDescriptors( | 2715 MaybeObject* maybe_map = new_map->CopyInstallDescriptors( |
| 2754 descriptor, new_descriptors); | 2716 descriptor, new_descriptors); |
| 2755 if (!maybe_map->To(&new_map)) { | 2717 if (!maybe_map->To(&new_map)) { |
| 2756 // Create a handle for the last created map to ensure it stays alive | 2718 // Create a handle for the last created map to ensure it stays alive |
| 2757 // during GC. Its descriptor array is too large, but it will be | 2719 // during GC. Its descriptor array is too large, but it will be |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2804 if (name->IsSymbol()) return value; | 2766 if (name->IsSymbol()) return value; |
| 2805 Isolate* isolate = GetIsolate(); | 2767 Isolate* isolate = GetIsolate(); |
| 2806 HandleScope scope(isolate); | 2768 HandleScope scope(isolate); |
| 2807 Handle<JSObject> this_handle(this); | 2769 Handle<JSObject> this_handle(this); |
| 2808 Handle<String> name_handle(String::cast(name)); | 2770 Handle<String> name_handle(String::cast(name)); |
| 2809 Handle<Object> value_handle(value, isolate); | 2771 Handle<Object> value_handle(value, isolate); |
| 2810 Handle<InterceptorInfo> interceptor(GetNamedInterceptor()); | 2772 Handle<InterceptorInfo> interceptor(GetNamedInterceptor()); |
| 2811 if (!interceptor->setter()->IsUndefined()) { | 2773 if (!interceptor->setter()->IsUndefined()) { |
| 2812 LOG(isolate, ApiNamedPropertyAccess("interceptor-named-set", this, name)); | 2774 LOG(isolate, ApiNamedPropertyAccess("interceptor-named-set", this, name)); |
| 2813 PropertyCallbackArguments args(isolate, interceptor->data(), this, this); | 2775 PropertyCallbackArguments args(isolate, interceptor->data(), this, this); |
| 2814 v8::NamedPropertySetter setter = | 2776 v8::NamedPropertySetterCallback setter = |
| 2815 v8::ToCData<v8::NamedPropertySetter>(interceptor->setter()); | 2777 v8::ToCData<v8::NamedPropertySetterCallback>(interceptor->setter()); |
| 2816 Handle<Object> value_unhole(value->IsTheHole() ? | 2778 Handle<Object> value_unhole(value->IsTheHole() ? |
| 2817 isolate->heap()->undefined_value() : | 2779 isolate->heap()->undefined_value() : |
| 2818 value, | 2780 value, |
| 2819 isolate); | 2781 isolate); |
| 2820 v8::Handle<v8::Value> result = args.Call(setter, | 2782 v8::Handle<v8::Value> result = args.Call(setter, |
| 2821 v8::Utils::ToLocal(name_handle), | 2783 v8::Utils::ToLocal(name_handle), |
| 2822 v8::Utils::ToLocal(value_unhole)); | 2784 v8::Utils::ToLocal(value_unhole)); |
| 2823 RETURN_IF_SCHEDULED_EXCEPTION(isolate); | 2785 RETURN_IF_SCHEDULED_EXCEPTION(isolate); |
| 2824 if (!result.IsEmpty()) return *value_handle; | 2786 if (!result.IsEmpty()) return *value_handle; |
| 2825 } | 2787 } |
| 2826 MaybeObject* raw_result = | 2788 MaybeObject* raw_result = |
| 2827 this_handle->SetPropertyPostInterceptor(*name_handle, | 2789 this_handle->SetPropertyPostInterceptor(*name_handle, |
| 2828 *value_handle, | 2790 *value_handle, |
| 2829 attributes, | 2791 attributes, |
| 2830 strict_mode, | 2792 strict_mode); |
| 2831 PERFORM_EXTENSIBILITY_CHECK); | |
| 2832 RETURN_IF_SCHEDULED_EXCEPTION(isolate); | 2793 RETURN_IF_SCHEDULED_EXCEPTION(isolate); |
| 2833 return raw_result; | 2794 return raw_result; |
| 2834 } | 2795 } |
| 2835 | 2796 |
| 2836 | 2797 |
| 2837 Handle<Object> JSReceiver::SetProperty(Handle<JSReceiver> object, | 2798 Handle<Object> JSReceiver::SetProperty(Handle<JSReceiver> object, |
| 2838 Handle<Name> key, | 2799 Handle<Name> key, |
| 2839 Handle<Object> value, | 2800 Handle<Object> value, |
| 2840 PropertyAttributes attributes, | 2801 PropertyAttributes attributes, |
| 2841 StrictModeFlag strict_mode) { | 2802 StrictModeFlag strict_mode) { |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2907 Handle<Object> args[2] = { name_handle, receiver_handle }; | 2868 Handle<Object> args[2] = { name_handle, receiver_handle }; |
| 2908 Handle<Object> error = | 2869 Handle<Object> error = |
| 2909 isolate->factory()->NewTypeError("incompatible_method_receiver", | 2870 isolate->factory()->NewTypeError("incompatible_method_receiver", |
| 2910 HandleVector(args, | 2871 HandleVector(args, |
| 2911 ARRAY_SIZE(args))); | 2872 ARRAY_SIZE(args))); |
| 2912 return isolate->Throw(*error); | 2873 return isolate->Throw(*error); |
| 2913 } | 2874 } |
| 2914 // TODO(rossberg): Support symbols in the API. | 2875 // TODO(rossberg): Support symbols in the API. |
| 2915 if (name->IsSymbol()) return value; | 2876 if (name->IsSymbol()) return value; |
| 2916 Object* call_obj = data->setter(); | 2877 Object* call_obj = data->setter(); |
| 2917 v8::AccessorSetter call_fun = v8::ToCData<v8::AccessorSetter>(call_obj); | 2878 v8::AccessorSetterCallback call_fun = |
| 2879 v8::ToCData<v8::AccessorSetterCallback>(call_obj); |
| 2918 if (call_fun == NULL) return value; | 2880 if (call_fun == NULL) return value; |
| 2919 Handle<String> key(String::cast(name)); | 2881 Handle<String> key(String::cast(name)); |
| 2920 LOG(isolate, ApiNamedPropertyAccess("store", this, name)); | 2882 LOG(isolate, ApiNamedPropertyAccess("store", this, name)); |
| 2921 PropertyCallbackArguments args( | 2883 PropertyCallbackArguments args( |
| 2922 isolate, data->data(), this, JSObject::cast(holder)); | 2884 isolate, data->data(), this, JSObject::cast(holder)); |
| 2923 args.Call(call_fun, | 2885 args.Call(call_fun, |
| 2924 v8::Utils::ToLocal(key), | 2886 v8::Utils::ToLocal(key), |
| 2925 v8::Utils::ToLocal(value_handle)); | 2887 v8::Utils::ToLocal(value_handle)); |
| 2926 RETURN_IF_SCHEDULED_EXCEPTION(isolate); | 2888 RETURN_IF_SCHEDULED_EXCEPTION(isolate); |
| 2927 return *value_handle; | 2889 return *value_handle; |
| (...skipping 466 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3394 Object* obj = result->GetCallbackObject(); | 3356 Object* obj = result->GetCallbackObject(); |
| 3395 if (obj->IsAccessorInfo()) { | 3357 if (obj->IsAccessorInfo()) { |
| 3396 AccessorInfo* info = AccessorInfo::cast(obj); | 3358 AccessorInfo* info = AccessorInfo::cast(obj); |
| 3397 if (info->all_can_write()) { | 3359 if (info->all_can_write()) { |
| 3398 return SetPropertyWithCallback(result->GetCallbackObject(), | 3360 return SetPropertyWithCallback(result->GetCallbackObject(), |
| 3399 name, | 3361 name, |
| 3400 value, | 3362 value, |
| 3401 result->holder(), | 3363 result->holder(), |
| 3402 strict_mode); | 3364 strict_mode); |
| 3403 } | 3365 } |
| 3366 } else if (obj->IsAccessorPair()) { |
| 3367 AccessorPair* pair = AccessorPair::cast(obj); |
| 3368 if (pair->all_can_read()) { |
| 3369 return SetPropertyWithCallback(result->GetCallbackObject(), |
| 3370 name, |
| 3371 value, |
| 3372 result->holder(), |
| 3373 strict_mode); |
| 3374 } |
| 3404 } | 3375 } |
| 3405 break; | 3376 break; |
| 3406 } | 3377 } |
| 3407 case INTERCEPTOR: { | 3378 case INTERCEPTOR: { |
| 3408 // Try lookup real named properties. Note that only property can be | 3379 // Try lookup real named properties. Note that only property can be |
| 3409 // set is callbacks marked as ALL_CAN_WRITE on the prototype chain. | 3380 // set is callbacks marked as ALL_CAN_WRITE on the prototype chain. |
| 3410 LookupResult r(GetIsolate()); | 3381 LookupResult r(GetIsolate()); |
| 3411 LookupRealNamedProperty(name, &r); | 3382 LookupRealNamedProperty(name, &r); |
| 3412 if (r.IsProperty()) { | 3383 if (r.IsProperty()) { |
| 3413 return SetPropertyWithFailedAccessCheck(&r, | 3384 return SetPropertyWithFailedAccessCheck(&r, |
| (...skipping 361 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3775 Handle<Object> JSObject::TryMigrateInstance(Handle<JSObject> object) { | 3746 Handle<Object> JSObject::TryMigrateInstance(Handle<JSObject> object) { |
| 3776 CALL_HEAP_FUNCTION( | 3747 CALL_HEAP_FUNCTION( |
| 3777 object->GetIsolate(), | 3748 object->GetIsolate(), |
| 3778 object->MigrateInstance(), | 3749 object->MigrateInstance(), |
| 3779 Object); | 3750 Object); |
| 3780 } | 3751 } |
| 3781 | 3752 |
| 3782 | 3753 |
| 3783 Handle<Map> Map::GeneralizeRepresentation(Handle<Map> map, | 3754 Handle<Map> Map::GeneralizeRepresentation(Handle<Map> map, |
| 3784 int modify_index, | 3755 int modify_index, |
| 3785 Representation representation) { | 3756 Representation representation, |
| 3757 StoreMode store_mode) { |
| 3786 CALL_HEAP_FUNCTION( | 3758 CALL_HEAP_FUNCTION( |
| 3787 map->GetIsolate(), | 3759 map->GetIsolate(), |
| 3788 map->GeneralizeRepresentation(modify_index, representation), | 3760 map->GeneralizeRepresentation(modify_index, representation, store_mode), |
| 3789 Map); | 3761 Map); |
| 3790 } | 3762 } |
| 3791 | 3763 |
| 3792 | 3764 |
| 3765 static MaybeObject* SetPropertyUsingTransition(LookupResult* lookup, |
| 3766 Handle<Name> name, |
| 3767 Handle<Object> value, |
| 3768 PropertyAttributes attributes) { |
| 3769 Map* transition_map = lookup->GetTransitionTarget(); |
| 3770 int descriptor = transition_map->LastAdded(); |
| 3771 |
| 3772 DescriptorArray* descriptors = transition_map->instance_descriptors(); |
| 3773 PropertyDetails details = descriptors->GetDetails(descriptor); |
| 3774 |
| 3775 if (details.type() == CALLBACKS || attributes != details.attributes()) { |
| 3776 // AddProperty will either normalize the object, or create a new fast copy |
| 3777 // of the map. If we get a fast copy of the map, all field representations |
| 3778 // will be tagged since the transition is omitted. |
| 3779 return lookup->holder()->AddProperty( |
| 3780 *name, *value, attributes, kNonStrictMode, |
| 3781 JSReceiver::CERTAINLY_NOT_STORE_FROM_KEYED, |
| 3782 JSReceiver::OMIT_EXTENSIBILITY_CHECK, |
| 3783 JSObject::FORCE_TAGGED, FORCE_FIELD, OMIT_TRANSITION); |
| 3784 } |
| 3785 |
| 3786 // Keep the target CONSTANT if the same value is stored. |
| 3787 // TODO(verwaest): Also support keeping the placeholder |
| 3788 // (value->IsUninitialized) as constant. |
| 3789 if (details.type() == CONSTANT && |
| 3790 descriptors->GetValue(descriptor) == *value) { |
| 3791 lookup->holder()->set_map(transition_map); |
| 3792 return *value; |
| 3793 } |
| 3794 |
| 3795 Representation representation = details.representation(); |
| 3796 |
| 3797 if (!value->FitsRepresentation(representation) || |
| 3798 details.type() == CONSTANT) { |
| 3799 MaybeObject* maybe_map = transition_map->GeneralizeRepresentation( |
| 3800 descriptor, value->OptimalRepresentation(), FORCE_FIELD); |
| 3801 if (!maybe_map->To(&transition_map)) return maybe_map; |
| 3802 Object* back = transition_map->GetBackPointer(); |
| 3803 if (back->IsMap()) { |
| 3804 MaybeObject* maybe_failure = |
| 3805 lookup->holder()->MigrateToMap(Map::cast(back)); |
| 3806 if (maybe_failure->IsFailure()) return maybe_failure; |
| 3807 } |
| 3808 descriptors = transition_map->instance_descriptors(); |
| 3809 representation = descriptors->GetDetails(descriptor).representation(); |
| 3810 } |
| 3811 |
| 3812 int field_index = descriptors->GetFieldIndex(descriptor); |
| 3813 return lookup->holder()->AddFastPropertyUsingMap( |
| 3814 transition_map, *name, *value, field_index, representation); |
| 3815 } |
| 3816 |
| 3817 |
| 3818 static MaybeObject* SetPropertyToField(LookupResult* lookup, |
| 3819 Handle<Name> name, |
| 3820 Handle<Object> value) { |
| 3821 Representation representation = lookup->representation(); |
| 3822 if (!value->FitsRepresentation(representation) || |
| 3823 lookup->type() == CONSTANT) { |
| 3824 MaybeObject* maybe_failure = |
| 3825 lookup->holder()->GeneralizeFieldRepresentation( |
| 3826 lookup->GetDescriptorIndex(), |
| 3827 value->OptimalRepresentation(), |
| 3828 FORCE_FIELD); |
| 3829 if (maybe_failure->IsFailure()) return maybe_failure; |
| 3830 DescriptorArray* desc = lookup->holder()->map()->instance_descriptors(); |
| 3831 int descriptor = lookup->GetDescriptorIndex(); |
| 3832 representation = desc->GetDetails(descriptor).representation(); |
| 3833 } |
| 3834 |
| 3835 if (FLAG_track_double_fields && representation.IsDouble()) { |
| 3836 HeapNumber* storage = HeapNumber::cast(lookup->holder()->RawFastPropertyAt( |
| 3837 lookup->GetFieldIndex().field_index())); |
| 3838 storage->set_value(value->Number()); |
| 3839 return *value; |
| 3840 } |
| 3841 |
| 3842 lookup->holder()->FastPropertyAtPut( |
| 3843 lookup->GetFieldIndex().field_index(), *value); |
| 3844 return *value; |
| 3845 } |
| 3846 |
| 3847 |
| 3848 static MaybeObject* ConvertAndSetLocalProperty(LookupResult* lookup, |
| 3849 Name* name, |
| 3850 Object* value, |
| 3851 PropertyAttributes attributes) { |
| 3852 JSObject* object = lookup->holder(); |
| 3853 if (object->TooManyFastProperties()) { |
| 3854 MaybeObject* maybe_failure = object->NormalizeProperties( |
| 3855 CLEAR_INOBJECT_PROPERTIES, 0); |
| 3856 if (maybe_failure->IsFailure()) return maybe_failure; |
| 3857 } |
| 3858 |
| 3859 if (!object->HasFastProperties()) { |
| 3860 return object->ReplaceSlowProperty(name, value, attributes); |
| 3861 } |
| 3862 |
| 3863 int descriptor_index = lookup->GetDescriptorIndex(); |
| 3864 if (lookup->GetAttributes() == attributes) { |
| 3865 MaybeObject* maybe_failure = object->GeneralizeFieldRepresentation( |
| 3866 descriptor_index, Representation::Tagged(), FORCE_FIELD); |
| 3867 if (maybe_failure->IsFailure()) return maybe_failure; |
| 3868 } else { |
| 3869 Map* map; |
| 3870 MaybeObject* maybe_map = object->map()->CopyGeneralizeAllRepresentations( |
| 3871 descriptor_index, FORCE_FIELD, attributes, "attributes mismatch"); |
| 3872 if (!maybe_map->To(&map)) return maybe_map; |
| 3873 MaybeObject* maybe_failure = object->MigrateToMap(map); |
| 3874 if (maybe_failure->IsFailure()) return maybe_failure; |
| 3875 } |
| 3876 |
| 3877 DescriptorArray* descriptors = object->map()->instance_descriptors(); |
| 3878 int index = descriptors->GetDetails(descriptor_index).field_index(); |
| 3879 object->FastPropertyAtPut(index, value); |
| 3880 return value; |
| 3881 } |
| 3882 |
| 3883 |
| 3884 static MaybeObject* SetPropertyToFieldWithAttributes( |
| 3885 LookupResult* lookup, |
| 3886 Handle<Name> name, |
| 3887 Handle<Object> value, |
| 3888 PropertyAttributes attributes) { |
| 3889 if (lookup->GetAttributes() == attributes) { |
| 3890 if (value->IsUninitialized()) return *value; |
| 3891 return SetPropertyToField(lookup, name, value); |
| 3892 } else { |
| 3893 return ConvertAndSetLocalProperty(lookup, *name, *value, attributes); |
| 3894 } |
| 3895 } |
| 3896 |
| 3897 |
| 3793 MaybeObject* JSObject::SetPropertyForResult(LookupResult* lookup, | 3898 MaybeObject* JSObject::SetPropertyForResult(LookupResult* lookup, |
| 3794 Name* name_raw, | 3899 Name* name_raw, |
| 3795 Object* value_raw, | 3900 Object* value_raw, |
| 3796 PropertyAttributes attributes, | 3901 PropertyAttributes attributes, |
| 3797 StrictModeFlag strict_mode, | 3902 StrictModeFlag strict_mode, |
| 3798 StoreFromKeyed store_mode) { | 3903 StoreFromKeyed store_mode) { |
| 3799 Heap* heap = GetHeap(); | 3904 Heap* heap = GetHeap(); |
| 3800 Isolate* isolate = heap->isolate(); | 3905 Isolate* isolate = heap->isolate(); |
| 3801 // Make sure that the top context does not change when doing callbacks or | 3906 // Make sure that the top context does not change when doing callbacks or |
| 3802 // interceptor calls. | 3907 // interceptor calls. |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3871 old_value = Object::GetProperty(self, name); | 3976 old_value = Object::GetProperty(self, name); |
| 3872 } | 3977 } |
| 3873 | 3978 |
| 3874 // This is a real property that is not read-only, or it is a | 3979 // This is a real property that is not read-only, or it is a |
| 3875 // transition or null descriptor and there are no setters in the prototypes. | 3980 // transition or null descriptor and there are no setters in the prototypes. |
| 3876 MaybeObject* result = *value; | 3981 MaybeObject* result = *value; |
| 3877 switch (lookup->type()) { | 3982 switch (lookup->type()) { |
| 3878 case NORMAL: | 3983 case NORMAL: |
| 3879 result = lookup->holder()->SetNormalizedProperty(lookup, *value); | 3984 result = lookup->holder()->SetNormalizedProperty(lookup, *value); |
| 3880 break; | 3985 break; |
| 3881 case FIELD: { | 3986 case FIELD: |
| 3882 Representation representation = lookup->representation(); | 3987 result = SetPropertyToField(lookup, name, value); |
| 3883 if (!value->FitsRepresentation(representation)) { | |
| 3884 MaybeObject* maybe_failure = | |
| 3885 lookup->holder()->GeneralizeFieldRepresentation( | |
| 3886 lookup->GetDescriptorIndex(), value->OptimalRepresentation()); | |
| 3887 if (maybe_failure->IsFailure()) return maybe_failure; | |
| 3888 DescriptorArray* desc = lookup->holder()->map()->instance_descriptors(); | |
| 3889 int descriptor = lookup->GetDescriptorIndex(); | |
| 3890 representation = desc->GetDetails(descriptor).representation(); | |
| 3891 } | |
| 3892 if (FLAG_track_double_fields && representation.IsDouble()) { | |
| 3893 HeapNumber* storage = | |
| 3894 HeapNumber::cast(lookup->holder()->RawFastPropertyAt( | |
| 3895 lookup->GetFieldIndex().field_index())); | |
| 3896 storage->set_value(value->Number()); | |
| 3897 result = *value; | |
| 3898 break; | |
| 3899 } | |
| 3900 lookup->holder()->FastPropertyAtPut( | |
| 3901 lookup->GetFieldIndex().field_index(), *value); | |
| 3902 result = *value; | |
| 3903 break; | 3988 break; |
| 3904 } | |
| 3905 case CONSTANT: | 3989 case CONSTANT: |
| 3906 // Only replace the constant if necessary. | 3990 // Only replace the constant if necessary. |
| 3907 if (*value == lookup->GetConstant()) return *value; | 3991 if (*value == lookup->GetConstant()) return *value; |
| 3908 // Preserve the attributes of this existing property. | 3992 result = SetPropertyToField(lookup, name, value); |
| 3909 attributes = lookup->GetAttributes(); | |
| 3910 result = lookup->holder()->ConvertDescriptorToField( | |
| 3911 *name, *value, attributes); | |
| 3912 break; | 3993 break; |
| 3913 case CALLBACKS: { | 3994 case CALLBACKS: { |
| 3914 Object* callback_object = lookup->GetCallbackObject(); | 3995 Object* callback_object = lookup->GetCallbackObject(); |
| 3915 return self->SetPropertyWithCallback( | 3996 return self->SetPropertyWithCallback( |
| 3916 callback_object, *name, *value, lookup->holder(), strict_mode); | 3997 callback_object, *name, *value, lookup->holder(), strict_mode); |
| 3917 } | 3998 } |
| 3918 case INTERCEPTOR: | 3999 case INTERCEPTOR: |
| 3919 result = lookup->holder()->SetPropertyWithInterceptor( | 4000 result = lookup->holder()->SetPropertyWithInterceptor( |
| 3920 *name, *value, attributes, strict_mode); | 4001 *name, *value, attributes, strict_mode); |
| 3921 break; | 4002 break; |
| 3922 case TRANSITION: { | 4003 case TRANSITION: { |
| 3923 Map* transition_map = lookup->GetTransitionTarget(); | 4004 result = SetPropertyUsingTransition(lookup, name, value, attributes); |
| 3924 int descriptor = transition_map->LastAdded(); | |
| 3925 | |
| 3926 DescriptorArray* descriptors = transition_map->instance_descriptors(); | |
| 3927 PropertyDetails details = descriptors->GetDetails(descriptor); | |
| 3928 | |
| 3929 if (details.type() == FIELD) { | |
| 3930 if (attributes == details.attributes()) { | |
| 3931 Representation representation = details.representation(); | |
| 3932 if (!value->FitsRepresentation(representation)) { | |
| 3933 MaybeObject* maybe_map = transition_map->GeneralizeRepresentation( | |
| 3934 descriptor, value->OptimalRepresentation()); | |
| 3935 if (!maybe_map->To(&transition_map)) return maybe_map; | |
| 3936 Object* back = transition_map->GetBackPointer(); | |
| 3937 if (back->IsMap()) { | |
| 3938 MaybeObject* maybe_failure = | |
| 3939 lookup->holder()->MigrateToMap(Map::cast(back)); | |
| 3940 if (maybe_failure->IsFailure()) return maybe_failure; | |
| 3941 } | |
| 3942 DescriptorArray* desc = transition_map->instance_descriptors(); | |
| 3943 int descriptor = transition_map->LastAdded(); | |
| 3944 representation = desc->GetDetails(descriptor).representation(); | |
| 3945 } | |
| 3946 int field_index = descriptors->GetFieldIndex(descriptor); | |
| 3947 result = lookup->holder()->AddFastPropertyUsingMap( | |
| 3948 transition_map, *name, *value, field_index, representation); | |
| 3949 } else { | |
| 3950 result = lookup->holder()->ConvertDescriptorToField( | |
| 3951 *name, *value, attributes); | |
| 3952 } | |
| 3953 } else if (details.type() == CALLBACKS) { | |
| 3954 result = lookup->holder()->ConvertDescriptorToField( | |
| 3955 *name, *value, attributes); | |
| 3956 } else { | |
| 3957 ASSERT(details.type() == CONSTANT); | |
| 3958 | |
| 3959 Object* constant = descriptors->GetValue(descriptor); | |
| 3960 if (constant == *value) { | |
| 3961 // If the same constant function is being added we can simply | |
| 3962 // transition to the target map. | |
| 3963 lookup->holder()->set_map(transition_map); | |
| 3964 result = constant; | |
| 3965 } else { | |
| 3966 // Otherwise, replace with a map transition to a new map with a FIELD, | |
| 3967 // even if the value is a constant function. | |
| 3968 result = lookup->holder()->ConvertTransitionToMapTransition( | |
| 3969 lookup->GetTransitionIndex(), *name, *value, attributes); | |
| 3970 } | |
| 3971 } | |
| 3972 break; | 4005 break; |
| 3973 } | 4006 } |
| 3974 case HANDLER: | 4007 case HANDLER: |
| 3975 case NONEXISTENT: | 4008 case NONEXISTENT: |
| 3976 UNREACHABLE(); | 4009 UNREACHABLE(); |
| 3977 } | 4010 } |
| 3978 | 4011 |
| 3979 Handle<Object> hresult; | 4012 Handle<Object> hresult; |
| 3980 if (!result->ToHandle(&hresult, isolate)) return result; | 4013 if (!result->ToHandle(&hresult, isolate)) return result; |
| 3981 | 4014 |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4020 *key, *value, attributes, value_type, mode), | 4053 *key, *value, attributes, value_type, mode), |
| 4021 Object); | 4054 Object); |
| 4022 } | 4055 } |
| 4023 | 4056 |
| 4024 | 4057 |
| 4025 MaybeObject* JSObject::SetLocalPropertyIgnoreAttributes( | 4058 MaybeObject* JSObject::SetLocalPropertyIgnoreAttributes( |
| 4026 Name* name_raw, | 4059 Name* name_raw, |
| 4027 Object* value_raw, | 4060 Object* value_raw, |
| 4028 PropertyAttributes attributes, | 4061 PropertyAttributes attributes, |
| 4029 ValueType value_type, | 4062 ValueType value_type, |
| 4030 StoreMode mode) { | 4063 StoreMode mode, |
| 4064 ExtensibilityCheck extensibility_check) { |
| 4031 // Make sure that the top context does not change when doing callbacks or | 4065 // Make sure that the top context does not change when doing callbacks or |
| 4032 // interceptor calls. | 4066 // interceptor calls. |
| 4033 AssertNoContextChange ncc; | 4067 AssertNoContextChange ncc; |
| 4034 Isolate* isolate = GetIsolate(); | 4068 Isolate* isolate = GetIsolate(); |
| 4035 LookupResult lookup(isolate); | 4069 LookupResult lookup(isolate); |
| 4036 LocalLookup(name_raw, &lookup, true); | 4070 LocalLookup(name_raw, &lookup, true); |
| 4037 if (!lookup.IsFound()) map()->LookupTransition(this, name_raw, &lookup); | 4071 if (!lookup.IsFound()) map()->LookupTransition(this, name_raw, &lookup); |
| 4038 // Check access rights if needed. | 4072 // Check access rights if needed. |
| 4039 if (IsAccessCheckNeeded()) { | 4073 if (IsAccessCheckNeeded()) { |
| 4040 if (!isolate->MayNamedAccess(this, name_raw, v8::ACCESS_SET)) { | 4074 if (!isolate->MayNamedAccess(this, name_raw, v8::ACCESS_SET)) { |
| 4041 return SetPropertyWithFailedAccessCheck(&lookup, | 4075 return SetPropertyWithFailedAccessCheck(&lookup, |
| 4042 name_raw, | 4076 name_raw, |
| 4043 value_raw, | 4077 value_raw, |
| 4044 false, | 4078 false, |
| 4045 kNonStrictMode); | 4079 kNonStrictMode); |
| 4046 } | 4080 } |
| 4047 } | 4081 } |
| 4048 | 4082 |
| 4049 if (IsJSGlobalProxy()) { | 4083 if (IsJSGlobalProxy()) { |
| 4050 Object* proto = GetPrototype(); | 4084 Object* proto = GetPrototype(); |
| 4051 if (proto->IsNull()) return value_raw; | 4085 if (proto->IsNull()) return value_raw; |
| 4052 ASSERT(proto->IsJSGlobalObject()); | 4086 ASSERT(proto->IsJSGlobalObject()); |
| 4053 return JSObject::cast(proto)->SetLocalPropertyIgnoreAttributes( | 4087 return JSObject::cast(proto)->SetLocalPropertyIgnoreAttributes( |
| 4054 name_raw, | 4088 name_raw, |
| 4055 value_raw, | 4089 value_raw, |
| 4056 attributes, | 4090 attributes, |
| 4057 value_type, | 4091 value_type, |
| 4058 mode); | 4092 mode, |
| 4093 extensibility_check); |
| 4059 } | 4094 } |
| 4060 | 4095 |
| 4061 // Check for accessor in prototype chain removed here in clone. | 4096 // Check for accessor in prototype chain removed here in clone. |
| 4062 if (!lookup.IsFound()) { | 4097 if (!lookup.IsFound()) { |
| 4063 // Neither properties nor transitions found. | 4098 // Neither properties nor transitions found. |
| 4064 return AddProperty( | 4099 return AddProperty( |
| 4065 name_raw, value_raw, attributes, kNonStrictMode, | 4100 name_raw, value_raw, attributes, kNonStrictMode, |
| 4066 MAY_BE_STORE_FROM_KEYED, PERFORM_EXTENSIBILITY_CHECK, value_type, mode); | 4101 MAY_BE_STORE_FROM_KEYED, extensibility_check, value_type, mode); |
| 4067 } | 4102 } |
| 4068 | 4103 |
| 4069 // From this point on everything needs to be handlified. | 4104 // From this point on everything needs to be handlified. |
| 4070 HandleScope scope(isolate); | 4105 HandleScope scope(isolate); |
| 4071 Handle<JSObject> self(this); | 4106 Handle<JSObject> self(this); |
| 4072 Handle<Name> name(name_raw); | 4107 Handle<Name> name(name_raw); |
| 4073 Handle<Object> value(value_raw, isolate); | 4108 Handle<Object> value(value_raw, isolate); |
| 4074 | 4109 |
| 4075 Handle<Object> old_value(isolate->heap()->the_hole_value(), isolate); | 4110 Handle<Object> old_value(isolate->heap()->the_hole_value(), isolate); |
| 4076 PropertyAttributes old_attributes = ABSENT; | 4111 PropertyAttributes old_attributes = ABSENT; |
| 4077 bool is_observed = FLAG_harmony_observation && self->map()->is_observed(); | 4112 bool is_observed = FLAG_harmony_observation && self->map()->is_observed(); |
| 4078 if (is_observed && lookup.IsProperty()) { | 4113 if (is_observed && lookup.IsProperty()) { |
| 4079 if (lookup.IsDataProperty()) old_value = Object::GetProperty(self, name); | 4114 if (lookup.IsDataProperty()) old_value = Object::GetProperty(self, name); |
| 4080 old_attributes = lookup.GetAttributes(); | 4115 old_attributes = lookup.GetAttributes(); |
| 4081 } | 4116 } |
| 4082 | 4117 |
| 4083 // Check of IsReadOnly removed from here in clone. | 4118 // Check of IsReadOnly removed from here in clone. |
| 4084 MaybeObject* result = *value; | 4119 MaybeObject* result = *value; |
| 4085 switch (lookup.type()) { | 4120 switch (lookup.type()) { |
| 4086 case NORMAL: { | 4121 case NORMAL: |
| 4087 PropertyDetails details = PropertyDetails(attributes, NORMAL, 0); | 4122 result = self->ReplaceSlowProperty(*name, *value, attributes); |
| 4088 result = self->SetNormalizedProperty(*name, *value, details); | |
| 4089 break; | 4123 break; |
| 4090 } | 4124 case FIELD: |
| 4091 case FIELD: { | 4125 result = SetPropertyToFieldWithAttributes( |
| 4092 Representation representation = lookup.representation(); | 4126 &lookup, name, value, attributes); |
| 4093 Representation value_representation = | |
| 4094 value->OptimalRepresentation(value_type); | |
| 4095 if (value_representation.IsNone()) break; | |
| 4096 if (!value_representation.fits_into(representation)) { | |
| 4097 MaybeObject* maybe_failure = self->GeneralizeFieldRepresentation( | |
| 4098 lookup.GetDescriptorIndex(), value_representation); | |
| 4099 if (maybe_failure->IsFailure()) return maybe_failure; | |
| 4100 DescriptorArray* desc = self->map()->instance_descriptors(); | |
| 4101 int descriptor = lookup.GetDescriptorIndex(); | |
| 4102 representation = desc->GetDetails(descriptor).representation(); | |
| 4103 } | |
| 4104 if (FLAG_track_double_fields && representation.IsDouble()) { | |
| 4105 HeapNumber* storage = | |
| 4106 HeapNumber::cast(self->RawFastPropertyAt( | |
| 4107 lookup.GetFieldIndex().field_index())); | |
| 4108 storage->set_value(value->Number()); | |
| 4109 result = *value; | |
| 4110 break; | |
| 4111 } | |
| 4112 self->FastPropertyAtPut(lookup.GetFieldIndex().field_index(), *value); | |
| 4113 result = *value; | |
| 4114 break; | 4127 break; |
| 4115 } | |
| 4116 case CONSTANT: | 4128 case CONSTANT: |
| 4117 // Only replace the function if necessary. | 4129 // Only replace the constant if necessary. |
| 4118 if (*value != lookup.GetConstant()) { | 4130 if (lookup.GetAttributes() != attributes || |
| 4119 // Preserve the attributes of this existing property. | 4131 *value != lookup.GetConstant()) { |
| 4120 attributes = lookup.GetAttributes(); | 4132 result = SetPropertyToFieldWithAttributes( |
| 4121 result = self->ConvertDescriptorToField(*name, *value, attributes); | 4133 &lookup, name, value, attributes); |
| 4122 } | 4134 } |
| 4123 break; | 4135 break; |
| 4124 case CALLBACKS: | 4136 case CALLBACKS: |
| 4137 // Callbacks are not guaranteed to be installed on the receiver. Also |
| 4138 // perform a local lookup again. Fall through. |
| 4125 case INTERCEPTOR: | 4139 case INTERCEPTOR: |
| 4126 // Override callback in clone | 4140 self->LocalLookupRealNamedProperty(*name, &lookup); |
| 4127 result = self->ConvertDescriptorToField(*name, *value, attributes); | 4141 if (lookup.IsFound()) { |
| 4128 break; | 4142 if (lookup.IsPropertyCallbacks()) { |
| 4129 case TRANSITION: { | 4143 result = ConvertAndSetLocalProperty( |
| 4130 Map* transition_map = lookup.GetTransitionTarget(); | 4144 &lookup, *name, *value, attributes); |
| 4131 int descriptor = transition_map->LastAdded(); | 4145 } else if (lookup.IsNormal()) { |
| 4132 | 4146 result = self->ReplaceSlowProperty(*name, *value, attributes); |
| 4133 DescriptorArray* descriptors = transition_map->instance_descriptors(); | |
| 4134 PropertyDetails details = descriptors->GetDetails(descriptor); | |
| 4135 | |
| 4136 if (details.type() == FIELD) { | |
| 4137 if (attributes == details.attributes()) { | |
| 4138 Representation representation = details.representation(); | |
| 4139 Representation value_representation = | |
| 4140 value->OptimalRepresentation(value_type); | |
| 4141 if (!value_representation.fits_into(representation)) { | |
| 4142 MaybeObject* maybe_map = transition_map->GeneralizeRepresentation( | |
| 4143 descriptor, value_representation); | |
| 4144 if (!maybe_map->To(&transition_map)) return maybe_map; | |
| 4145 Object* back = transition_map->GetBackPointer(); | |
| 4146 if (back->IsMap()) { | |
| 4147 MaybeObject* maybe_failure = self->MigrateToMap(Map::cast(back)); | |
| 4148 if (maybe_failure->IsFailure()) return maybe_failure; | |
| 4149 } | |
| 4150 DescriptorArray* desc = transition_map->instance_descriptors(); | |
| 4151 int descriptor = transition_map->LastAdded(); | |
| 4152 representation = desc->GetDetails(descriptor).representation(); | |
| 4153 } | |
| 4154 int field_index = descriptors->GetFieldIndex(descriptor); | |
| 4155 result = self->AddFastPropertyUsingMap( | |
| 4156 transition_map, *name, *value, field_index, representation); | |
| 4157 } else { | 4147 } else { |
| 4158 result = self->ConvertDescriptorToField(*name, *value, attributes); | 4148 result = SetPropertyToFieldWithAttributes( |
| 4149 &lookup, name, value, attributes); |
| 4159 } | 4150 } |
| 4160 } else if (details.type() == CALLBACKS) { | |
| 4161 result = self->ConvertDescriptorToField(*name, *value, attributes); | |
| 4162 } else { | 4151 } else { |
| 4163 ASSERT(details.type() == CONSTANT); | 4152 result = self->AddProperty( |
| 4164 | 4153 *name, *value, attributes, kNonStrictMode, MAY_BE_STORE_FROM_KEYED, |
| 4165 // Replace transition to CONSTANT FUNCTION with a map transition to a | 4154 extensibility_check, value_type, mode); |
| 4166 // new map with a FIELD, even if the value is a function. | |
| 4167 result = self->ConvertTransitionToMapTransition( | |
| 4168 lookup.GetTransitionIndex(), *name, *value, attributes); | |
| 4169 } | 4155 } |
| 4170 break; | 4156 break; |
| 4171 } | 4157 case TRANSITION: |
| 4158 result = SetPropertyUsingTransition(&lookup, name, value, attributes); |
| 4159 break; |
| 4172 case HANDLER: | 4160 case HANDLER: |
| 4173 case NONEXISTENT: | 4161 case NONEXISTENT: |
| 4174 UNREACHABLE(); | 4162 UNREACHABLE(); |
| 4175 } | 4163 } |
| 4176 | 4164 |
| 4177 Handle<Object> hresult; | 4165 Handle<Object> hresult; |
| 4178 if (!result->ToHandle(&hresult, isolate)) return result; | 4166 if (!result->ToHandle(&hresult, isolate)) return result; |
| 4179 | 4167 |
| 4180 if (is_observed) { | 4168 if (is_observed) { |
| 4181 if (lookup.IsTransition()) { | 4169 if (lookup.IsTransition()) { |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4237 // callbacks or interceptor calls. | 4225 // callbacks or interceptor calls. |
| 4238 AssertNoContextChange ncc; | 4226 AssertNoContextChange ncc; |
| 4239 | 4227 |
| 4240 HandleScope scope(isolate); | 4228 HandleScope scope(isolate); |
| 4241 Handle<InterceptorInfo> interceptor(GetNamedInterceptor()); | 4229 Handle<InterceptorInfo> interceptor(GetNamedInterceptor()); |
| 4242 Handle<JSObject> receiver_handle(receiver); | 4230 Handle<JSObject> receiver_handle(receiver); |
| 4243 Handle<JSObject> holder_handle(this); | 4231 Handle<JSObject> holder_handle(this); |
| 4244 Handle<String> name_handle(String::cast(name)); | 4232 Handle<String> name_handle(String::cast(name)); |
| 4245 PropertyCallbackArguments args(isolate, interceptor->data(), receiver, this); | 4233 PropertyCallbackArguments args(isolate, interceptor->data(), receiver, this); |
| 4246 if (!interceptor->query()->IsUndefined()) { | 4234 if (!interceptor->query()->IsUndefined()) { |
| 4247 v8::NamedPropertyQuery query = | 4235 v8::NamedPropertyQueryCallback query = |
| 4248 v8::ToCData<v8::NamedPropertyQuery>(interceptor->query()); | 4236 v8::ToCData<v8::NamedPropertyQueryCallback>(interceptor->query()); |
| 4249 LOG(isolate, | 4237 LOG(isolate, |
| 4250 ApiNamedPropertyAccess("interceptor-named-has", *holder_handle, name)); | 4238 ApiNamedPropertyAccess("interceptor-named-has", *holder_handle, name)); |
| 4251 v8::Handle<v8::Integer> result = | 4239 v8::Handle<v8::Integer> result = |
| 4252 args.Call(query, v8::Utils::ToLocal(name_handle)); | 4240 args.Call(query, v8::Utils::ToLocal(name_handle)); |
| 4253 if (!result.IsEmpty()) { | 4241 if (!result.IsEmpty()) { |
| 4254 ASSERT(result->IsInt32()); | 4242 ASSERT(result->IsInt32()); |
| 4255 return static_cast<PropertyAttributes>(result->Int32Value()); | 4243 return static_cast<PropertyAttributes>(result->Int32Value()); |
| 4256 } | 4244 } |
| 4257 } else if (!interceptor->getter()->IsUndefined()) { | 4245 } else if (!interceptor->getter()->IsUndefined()) { |
| 4258 v8::NamedPropertyGetter getter = | 4246 v8::NamedPropertyGetterCallback getter = |
| 4259 v8::ToCData<v8::NamedPropertyGetter>(interceptor->getter()); | 4247 v8::ToCData<v8::NamedPropertyGetterCallback>(interceptor->getter()); |
| 4260 LOG(isolate, | 4248 LOG(isolate, |
| 4261 ApiNamedPropertyAccess("interceptor-named-get-has", this, name)); | 4249 ApiNamedPropertyAccess("interceptor-named-get-has", this, name)); |
| 4262 v8::Handle<v8::Value> result = | 4250 v8::Handle<v8::Value> result = |
| 4263 args.Call(getter, v8::Utils::ToLocal(name_handle)); | 4251 args.Call(getter, v8::Utils::ToLocal(name_handle)); |
| 4264 if (!result.IsEmpty()) return DONT_ENUM; | 4252 if (!result.IsEmpty()) return DONT_ENUM; |
| 4265 } | 4253 } |
| 4266 return holder_handle->GetPropertyAttributePostInterceptor(*receiver_handle, | 4254 return holder_handle->GetPropertyAttributePostInterceptor(*receiver_handle, |
| 4267 *name_handle, | 4255 *name_handle, |
| 4268 continue_search); | 4256 continue_search); |
| 4269 } | 4257 } |
| (...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4369 Isolate* isolate = GetIsolate(); | 4357 Isolate* isolate = GetIsolate(); |
| 4370 // Make sure that the top context does not change when doing | 4358 // Make sure that the top context does not change when doing |
| 4371 // callbacks or interceptor calls. | 4359 // callbacks or interceptor calls. |
| 4372 AssertNoContextChange ncc; | 4360 AssertNoContextChange ncc; |
| 4373 HandleScope scope(isolate); | 4361 HandleScope scope(isolate); |
| 4374 Handle<InterceptorInfo> interceptor(GetIndexedInterceptor()); | 4362 Handle<InterceptorInfo> interceptor(GetIndexedInterceptor()); |
| 4375 Handle<JSReceiver> hreceiver(receiver); | 4363 Handle<JSReceiver> hreceiver(receiver); |
| 4376 Handle<JSObject> holder(this); | 4364 Handle<JSObject> holder(this); |
| 4377 PropertyCallbackArguments args(isolate, interceptor->data(), receiver, this); | 4365 PropertyCallbackArguments args(isolate, interceptor->data(), receiver, this); |
| 4378 if (!interceptor->query()->IsUndefined()) { | 4366 if (!interceptor->query()->IsUndefined()) { |
| 4379 v8::IndexedPropertyQuery query = | 4367 v8::IndexedPropertyQueryCallback query = |
| 4380 v8::ToCData<v8::IndexedPropertyQuery>(interceptor->query()); | 4368 v8::ToCData<v8::IndexedPropertyQueryCallback>(interceptor->query()); |
| 4381 LOG(isolate, | 4369 LOG(isolate, |
| 4382 ApiIndexedPropertyAccess("interceptor-indexed-has", this, index)); | 4370 ApiIndexedPropertyAccess("interceptor-indexed-has", this, index)); |
| 4383 v8::Handle<v8::Integer> result = args.Call(query, index); | 4371 v8::Handle<v8::Integer> result = args.Call(query, index); |
| 4384 if (!result.IsEmpty()) | 4372 if (!result.IsEmpty()) |
| 4385 return static_cast<PropertyAttributes>(result->Int32Value()); | 4373 return static_cast<PropertyAttributes>(result->Int32Value()); |
| 4386 } else if (!interceptor->getter()->IsUndefined()) { | 4374 } else if (!interceptor->getter()->IsUndefined()) { |
| 4387 v8::IndexedPropertyGetter getter = | 4375 v8::IndexedPropertyGetterCallback getter = |
| 4388 v8::ToCData<v8::IndexedPropertyGetter>(interceptor->getter()); | 4376 v8::ToCData<v8::IndexedPropertyGetterCallback>(interceptor->getter()); |
| 4389 LOG(isolate, | 4377 LOG(isolate, |
| 4390 ApiIndexedPropertyAccess("interceptor-indexed-get-has", this, index)); | 4378 ApiIndexedPropertyAccess("interceptor-indexed-get-has", this, index)); |
| 4391 v8::Handle<v8::Value> result = args.Call(getter, index); | 4379 v8::Handle<v8::Value> result = args.Call(getter, index); |
| 4392 if (!result.IsEmpty()) return NONE; | 4380 if (!result.IsEmpty()) return NONE; |
| 4393 } | 4381 } |
| 4394 | 4382 |
| 4395 return holder->GetElementAttributeWithoutInterceptor( | 4383 return holder->GetElementAttributeWithoutInterceptor( |
| 4396 *hreceiver, index, continue_search); | 4384 *hreceiver, index, continue_search); |
| 4397 } | 4385 } |
| 4398 | 4386 |
| (...skipping 577 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4976 // dictionary. Put the identity hash into the new dictionary. | 4964 // dictionary. Put the identity hash into the new dictionary. |
| 4977 MaybeObject* insert_result = | 4965 MaybeObject* insert_result = |
| 4978 hashtable->Put(GetHeap()->identity_hash_string(), inline_value); | 4966 hashtable->Put(GetHeap()->identity_hash_string(), inline_value); |
| 4979 ObjectHashTable* new_table; | 4967 ObjectHashTable* new_table; |
| 4980 if (!insert_result->To(&new_table)) return insert_result; | 4968 if (!insert_result->To(&new_table)) return insert_result; |
| 4981 // We expect no resizing for the first insert. | 4969 // We expect no resizing for the first insert. |
| 4982 ASSERT_EQ(hashtable, new_table); | 4970 ASSERT_EQ(hashtable, new_table); |
| 4983 } | 4971 } |
| 4984 | 4972 |
| 4985 MaybeObject* store_result = | 4973 MaybeObject* store_result = |
| 4986 SetPropertyPostInterceptor(GetHeap()->hidden_string(), | 4974 SetLocalPropertyIgnoreAttributes(GetHeap()->hidden_string(), |
| 4987 hashtable, | 4975 hashtable, |
| 4988 DONT_ENUM, | 4976 DONT_ENUM, |
| 4989 kNonStrictMode, | 4977 OPTIMAL_REPRESENTATION, |
| 4990 OMIT_EXTENSIBILITY_CHECK, | 4978 ALLOW_AS_CONSTANT, |
| 4991 FORCE_FIELD); | 4979 OMIT_EXTENSIBILITY_CHECK); |
| 4992 if (store_result->IsFailure()) return store_result; | 4980 if (store_result->IsFailure()) return store_result; |
| 4993 return hashtable; | 4981 return hashtable; |
| 4994 } | 4982 } |
| 4995 | 4983 |
| 4996 | 4984 |
| 4997 MaybeObject* JSObject::SetHiddenPropertiesHashTable(Object* value) { | 4985 MaybeObject* JSObject::SetHiddenPropertiesHashTable(Object* value) { |
| 4998 ASSERT(!IsJSGlobalProxy()); | 4986 ASSERT(!IsJSGlobalProxy()); |
| 4999 // We can store the identity hash inline iff there is no backing store | 4987 // We can store the identity hash inline iff there is no backing store |
| 5000 // for hidden properties yet. | 4988 // for hidden properties yet. |
| 5001 ASSERT(HasHiddenProperties() != value->IsSmi()); | 4989 ASSERT(HasHiddenProperties() != value->IsSmi()); |
| 5002 if (HasFastProperties()) { | 4990 if (HasFastProperties()) { |
| 5003 // If the object has fast properties, check whether the first slot | 4991 // If the object has fast properties, check whether the first slot |
| 5004 // in the descriptor array matches the hidden string. Since the | 4992 // in the descriptor array matches the hidden string. Since the |
| 5005 // hidden strings hash code is zero (and no other name has hash | 4993 // hidden strings hash code is zero (and no other name has hash |
| 5006 // code zero) it will always occupy the first entry if present. | 4994 // code zero) it will always occupy the first entry if present. |
| 5007 DescriptorArray* descriptors = this->map()->instance_descriptors(); | 4995 DescriptorArray* descriptors = this->map()->instance_descriptors(); |
| 5008 if (descriptors->number_of_descriptors() > 0) { | 4996 if (descriptors->number_of_descriptors() > 0) { |
| 5009 int sorted_index = descriptors->GetSortedKeyIndex(0); | 4997 int sorted_index = descriptors->GetSortedKeyIndex(0); |
| 5010 if (descriptors->GetKey(sorted_index) == GetHeap()->hidden_string() && | 4998 if (descriptors->GetKey(sorted_index) == GetHeap()->hidden_string() && |
| 5011 sorted_index < map()->NumberOfOwnDescriptors()) { | 4999 sorted_index < map()->NumberOfOwnDescriptors()) { |
| 5012 ASSERT(descriptors->GetType(sorted_index) == FIELD); | 5000 ASSERT(descriptors->GetType(sorted_index) == FIELD); |
| 5013 FastPropertyAtPut(descriptors->GetFieldIndex(sorted_index), value); | 5001 FastPropertyAtPut(descriptors->GetFieldIndex(sorted_index), value); |
| 5014 return this; | 5002 return this; |
| 5015 } | 5003 } |
| 5016 } | 5004 } |
| 5017 } | 5005 } |
| 5018 MaybeObject* store_result = | 5006 MaybeObject* store_result = |
| 5019 SetPropertyPostInterceptor(GetHeap()->hidden_string(), | 5007 SetLocalPropertyIgnoreAttributes(GetHeap()->hidden_string(), |
| 5020 value, | 5008 value, |
| 5021 DONT_ENUM, | 5009 DONT_ENUM, |
| 5022 kNonStrictMode, | 5010 OPTIMAL_REPRESENTATION, |
| 5023 OMIT_EXTENSIBILITY_CHECK, | 5011 ALLOW_AS_CONSTANT, |
| 5024 FORCE_FIELD); | 5012 OMIT_EXTENSIBILITY_CHECK); |
| 5025 if (store_result->IsFailure()) return store_result; | 5013 if (store_result->IsFailure()) return store_result; |
| 5026 return this; | 5014 return this; |
| 5027 } | 5015 } |
| 5028 | 5016 |
| 5029 | 5017 |
| 5030 Handle<Object> JSObject::DeletePropertyPostInterceptor(Handle<JSObject> object, | 5018 Handle<Object> JSObject::DeletePropertyPostInterceptor(Handle<JSObject> object, |
| 5031 Handle<Name> name, | 5019 Handle<Name> name, |
| 5032 DeleteMode mode) { | 5020 DeleteMode mode) { |
| 5033 // Check local property, ignore interceptor. | 5021 // Check local property, ignore interceptor. |
| 5034 Isolate* isolate = object->GetIsolate(); | 5022 Isolate* isolate = object->GetIsolate(); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 5045 | 5033 |
| 5046 Handle<Object> JSObject::DeletePropertyWithInterceptor(Handle<JSObject> object, | 5034 Handle<Object> JSObject::DeletePropertyWithInterceptor(Handle<JSObject> object, |
| 5047 Handle<Name> name) { | 5035 Handle<Name> name) { |
| 5048 Isolate* isolate = object->GetIsolate(); | 5036 Isolate* isolate = object->GetIsolate(); |
| 5049 | 5037 |
| 5050 // TODO(rossberg): Support symbols in the API. | 5038 // TODO(rossberg): Support symbols in the API. |
| 5051 if (name->IsSymbol()) return isolate->factory()->false_value(); | 5039 if (name->IsSymbol()) return isolate->factory()->false_value(); |
| 5052 | 5040 |
| 5053 Handle<InterceptorInfo> interceptor(object->GetNamedInterceptor()); | 5041 Handle<InterceptorInfo> interceptor(object->GetNamedInterceptor()); |
| 5054 if (!interceptor->deleter()->IsUndefined()) { | 5042 if (!interceptor->deleter()->IsUndefined()) { |
| 5055 v8::NamedPropertyDeleter deleter = | 5043 v8::NamedPropertyDeleterCallback deleter = |
| 5056 v8::ToCData<v8::NamedPropertyDeleter>(interceptor->deleter()); | 5044 v8::ToCData<v8::NamedPropertyDeleterCallback>(interceptor->deleter()); |
| 5057 LOG(isolate, | 5045 LOG(isolate, |
| 5058 ApiNamedPropertyAccess("interceptor-named-delete", *object, *name)); | 5046 ApiNamedPropertyAccess("interceptor-named-delete", *object, *name)); |
| 5059 PropertyCallbackArguments args( | 5047 PropertyCallbackArguments args( |
| 5060 isolate, interceptor->data(), *object, *object); | 5048 isolate, interceptor->data(), *object, *object); |
| 5061 v8::Handle<v8::Boolean> result = | 5049 v8::Handle<v8::Boolean> result = |
| 5062 args.Call(deleter, v8::Utils::ToLocal(Handle<String>::cast(name))); | 5050 args.Call(deleter, v8::Utils::ToLocal(Handle<String>::cast(name))); |
| 5063 RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object); | 5051 RETURN_HANDLE_IF_SCHEDULED_EXCEPTION(isolate, Object); |
| 5064 if (!result.IsEmpty()) { | 5052 if (!result.IsEmpty()) { |
| 5065 ASSERT(result->IsBoolean()); | 5053 ASSERT(result->IsBoolean()); |
| 5066 Handle<Object> result_internal = v8::Utils::OpenHandle(*result); | 5054 Handle<Object> result_internal = v8::Utils::OpenHandle(*result); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 5078 | 5066 |
| 5079 MaybeObject* JSObject::DeleteElementWithInterceptor(uint32_t index) { | 5067 MaybeObject* JSObject::DeleteElementWithInterceptor(uint32_t index) { |
| 5080 Isolate* isolate = GetIsolate(); | 5068 Isolate* isolate = GetIsolate(); |
| 5081 Heap* heap = isolate->heap(); | 5069 Heap* heap = isolate->heap(); |
| 5082 // Make sure that the top context does not change when doing | 5070 // Make sure that the top context does not change when doing |
| 5083 // callbacks or interceptor calls. | 5071 // callbacks or interceptor calls. |
| 5084 AssertNoContextChange ncc; | 5072 AssertNoContextChange ncc; |
| 5085 HandleScope scope(isolate); | 5073 HandleScope scope(isolate); |
| 5086 Handle<InterceptorInfo> interceptor(GetIndexedInterceptor()); | 5074 Handle<InterceptorInfo> interceptor(GetIndexedInterceptor()); |
| 5087 if (interceptor->deleter()->IsUndefined()) return heap->false_value(); | 5075 if (interceptor->deleter()->IsUndefined()) return heap->false_value(); |
| 5088 v8::IndexedPropertyDeleter deleter = | 5076 v8::IndexedPropertyDeleterCallback deleter = |
| 5089 v8::ToCData<v8::IndexedPropertyDeleter>(interceptor->deleter()); | 5077 v8::ToCData<v8::IndexedPropertyDeleterCallback>(interceptor->deleter()); |
| 5090 Handle<JSObject> this_handle(this); | 5078 Handle<JSObject> this_handle(this); |
| 5091 LOG(isolate, | 5079 LOG(isolate, |
| 5092 ApiIndexedPropertyAccess("interceptor-indexed-delete", this, index)); | 5080 ApiIndexedPropertyAccess("interceptor-indexed-delete", this, index)); |
| 5093 PropertyCallbackArguments args(isolate, interceptor->data(), this, this); | 5081 PropertyCallbackArguments args(isolate, interceptor->data(), this, this); |
| 5094 v8::Handle<v8::Boolean> result = args.Call(deleter, index); | 5082 v8::Handle<v8::Boolean> result = args.Call(deleter, index); |
| 5095 RETURN_IF_SCHEDULED_EXCEPTION(isolate); | 5083 RETURN_IF_SCHEDULED_EXCEPTION(isolate); |
| 5096 if (!result.IsEmpty()) { | 5084 if (!result.IsEmpty()) { |
| 5097 ASSERT(result->IsBoolean()); | 5085 ASSERT(result->IsBoolean()); |
| 5098 Handle<Object> result_internal = v8::Utils::OpenHandle(*result); | 5086 Handle<Object> result_internal = v8::Utils::OpenHandle(*result); |
| 5099 result_internal->VerifyApiCallResultType(); | 5087 result_internal->VerifyApiCallResultType(); |
| (...skipping 846 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5946 } | 5934 } |
| 5947 } | 5935 } |
| 5948 return false; | 5936 return false; |
| 5949 } | 5937 } |
| 5950 | 5938 |
| 5951 | 5939 |
| 5952 void JSObject::DefineElementAccessor(Handle<JSObject> object, | 5940 void JSObject::DefineElementAccessor(Handle<JSObject> object, |
| 5953 uint32_t index, | 5941 uint32_t index, |
| 5954 Handle<Object> getter, | 5942 Handle<Object> getter, |
| 5955 Handle<Object> setter, | 5943 Handle<Object> setter, |
| 5956 PropertyAttributes attributes) { | 5944 PropertyAttributes attributes, |
| 5945 v8::AccessControl access_control) { |
| 5957 switch (object->GetElementsKind()) { | 5946 switch (object->GetElementsKind()) { |
| 5958 case FAST_SMI_ELEMENTS: | 5947 case FAST_SMI_ELEMENTS: |
| 5959 case FAST_ELEMENTS: | 5948 case FAST_ELEMENTS: |
| 5960 case FAST_DOUBLE_ELEMENTS: | 5949 case FAST_DOUBLE_ELEMENTS: |
| 5961 case FAST_HOLEY_SMI_ELEMENTS: | 5950 case FAST_HOLEY_SMI_ELEMENTS: |
| 5962 case FAST_HOLEY_ELEMENTS: | 5951 case FAST_HOLEY_ELEMENTS: |
| 5963 case FAST_HOLEY_DOUBLE_ELEMENTS: | 5952 case FAST_HOLEY_DOUBLE_ELEMENTS: |
| 5964 break; | 5953 break; |
| 5965 case EXTERNAL_PIXEL_ELEMENTS: | 5954 case EXTERNAL_PIXEL_ELEMENTS: |
| 5966 case EXTERNAL_BYTE_ELEMENTS: | 5955 case EXTERNAL_BYTE_ELEMENTS: |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6004 } | 5993 } |
| 6005 } | 5994 } |
| 6006 } | 5995 } |
| 6007 break; | 5996 break; |
| 6008 } | 5997 } |
| 6009 } | 5998 } |
| 6010 | 5999 |
| 6011 Isolate* isolate = object->GetIsolate(); | 6000 Isolate* isolate = object->GetIsolate(); |
| 6012 Handle<AccessorPair> accessors = isolate->factory()->NewAccessorPair(); | 6001 Handle<AccessorPair> accessors = isolate->factory()->NewAccessorPair(); |
| 6013 accessors->SetComponents(*getter, *setter); | 6002 accessors->SetComponents(*getter, *setter); |
| 6003 accessors->set_access_flags(access_control); |
| 6014 | 6004 |
| 6015 CALL_HEAP_FUNCTION_VOID( | 6005 CALL_HEAP_FUNCTION_VOID( |
| 6016 isolate, object->SetElementCallback(index, *accessors, attributes)); | 6006 isolate, object->SetElementCallback(index, *accessors, attributes)); |
| 6017 } | 6007 } |
| 6018 | 6008 |
| 6019 | 6009 |
| 6020 Handle<AccessorPair> JSObject::CreateAccessorPairFor(Handle<JSObject> object, | 6010 Handle<AccessorPair> JSObject::CreateAccessorPairFor(Handle<JSObject> object, |
| 6021 Handle<Name> name) { | 6011 Handle<Name> name) { |
| 6022 Isolate* isolate = object->GetIsolate(); | 6012 Isolate* isolate = object->GetIsolate(); |
| 6023 LookupResult result(isolate); | 6013 LookupResult result(isolate); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 6035 } | 6025 } |
| 6036 } | 6026 } |
| 6037 return isolate->factory()->NewAccessorPair(); | 6027 return isolate->factory()->NewAccessorPair(); |
| 6038 } | 6028 } |
| 6039 | 6029 |
| 6040 | 6030 |
| 6041 void JSObject::DefinePropertyAccessor(Handle<JSObject> object, | 6031 void JSObject::DefinePropertyAccessor(Handle<JSObject> object, |
| 6042 Handle<Name> name, | 6032 Handle<Name> name, |
| 6043 Handle<Object> getter, | 6033 Handle<Object> getter, |
| 6044 Handle<Object> setter, | 6034 Handle<Object> setter, |
| 6045 PropertyAttributes attributes) { | 6035 PropertyAttributes attributes, |
| 6036 v8::AccessControl access_control) { |
| 6046 // We could assert that the property is configurable here, but we would need | 6037 // We could assert that the property is configurable here, but we would need |
| 6047 // to do a lookup, which seems to be a bit of overkill. | 6038 // to do a lookup, which seems to be a bit of overkill. |
| 6048 bool only_attribute_changes = getter->IsNull() && setter->IsNull(); | 6039 bool only_attribute_changes = getter->IsNull() && setter->IsNull(); |
| 6049 if (object->HasFastProperties() && !only_attribute_changes && | 6040 if (object->HasFastProperties() && !only_attribute_changes && |
| 6041 access_control == v8::DEFAULT && |
| 6050 (object->map()->NumberOfOwnDescriptors() < | 6042 (object->map()->NumberOfOwnDescriptors() < |
| 6051 DescriptorArray::kMaxNumberOfDescriptors)) { | 6043 DescriptorArray::kMaxNumberOfDescriptors)) { |
| 6052 bool getterOk = getter->IsNull() || | 6044 bool getterOk = getter->IsNull() || |
| 6053 DefineFastAccessor(object, name, ACCESSOR_GETTER, getter, attributes); | 6045 DefineFastAccessor(object, name, ACCESSOR_GETTER, getter, attributes); |
| 6054 bool setterOk = !getterOk || setter->IsNull() || | 6046 bool setterOk = !getterOk || setter->IsNull() || |
| 6055 DefineFastAccessor(object, name, ACCESSOR_SETTER, setter, attributes); | 6047 DefineFastAccessor(object, name, ACCESSOR_SETTER, setter, attributes); |
| 6056 if (getterOk && setterOk) return; | 6048 if (getterOk && setterOk) return; |
| 6057 } | 6049 } |
| 6058 | 6050 |
| 6059 Handle<AccessorPair> accessors = CreateAccessorPairFor(object, name); | 6051 Handle<AccessorPair> accessors = CreateAccessorPairFor(object, name); |
| 6060 accessors->SetComponents(*getter, *setter); | 6052 accessors->SetComponents(*getter, *setter); |
| 6053 accessors->set_access_flags(access_control); |
| 6061 | 6054 |
| 6062 CALL_HEAP_FUNCTION_VOID( | 6055 CALL_HEAP_FUNCTION_VOID( |
| 6063 object->GetIsolate(), | 6056 object->GetIsolate(), |
| 6064 object->SetPropertyCallback(*name, *accessors, attributes)); | 6057 object->SetPropertyCallback(*name, *accessors, attributes)); |
| 6065 } | 6058 } |
| 6066 | 6059 |
| 6067 | 6060 |
| 6068 bool JSObject::CanSetCallback(Name* name) { | 6061 bool JSObject::CanSetCallback(Name* name) { |
| 6069 ASSERT(!IsAccessCheckNeeded() || | 6062 ASSERT(!IsAccessCheckNeeded() || |
| 6070 GetIsolate()->MayNamedAccess(this, name, v8::ACCESS_SET)); | 6063 GetIsolate()->MayNamedAccess(this, name, v8::ACCESS_SET)); |
| 6071 | 6064 |
| 6072 // Check if there is an API defined callback object which prohibits | 6065 // Check if there is an API defined callback object which prohibits |
| 6073 // callback overwriting in this object or its prototype chain. | 6066 // callback overwriting in this object or its prototype chain. |
| 6074 // This mechanism is needed for instance in a browser setting, where | 6067 // This mechanism is needed for instance in a browser setting, where |
| 6075 // certain accessors such as window.location should not be allowed | 6068 // certain accessors such as window.location should not be allowed |
| 6076 // to be overwritten because allowing overwriting could potentially | 6069 // to be overwritten because allowing overwriting could potentially |
| 6077 // cause security problems. | 6070 // cause security problems. |
| 6078 LookupResult callback_result(GetIsolate()); | 6071 LookupResult callback_result(GetIsolate()); |
| 6079 LookupCallbackProperty(name, &callback_result); | 6072 LookupCallbackProperty(name, &callback_result); |
| 6080 if (callback_result.IsFound()) { | 6073 if (callback_result.IsFound()) { |
| 6081 Object* obj = callback_result.GetCallbackObject(); | 6074 Object* obj = callback_result.GetCallbackObject(); |
| 6082 if (obj->IsAccessorInfo() && | 6075 if (obj->IsAccessorInfo()) { |
| 6083 AccessorInfo::cast(obj)->prohibits_overwriting()) { | 6076 return !AccessorInfo::cast(obj)->prohibits_overwriting(); |
| 6084 return false; | 6077 } |
| 6078 if (obj->IsAccessorPair()) { |
| 6079 return !AccessorPair::cast(obj)->prohibits_overwriting(); |
| 6085 } | 6080 } |
| 6086 } | 6081 } |
| 6087 | |
| 6088 return true; | 6082 return true; |
| 6089 } | 6083 } |
| 6090 | 6084 |
| 6091 | 6085 |
| 6092 MaybeObject* JSObject::SetElementCallback(uint32_t index, | 6086 MaybeObject* JSObject::SetElementCallback(uint32_t index, |
| 6093 Object* structure, | 6087 Object* structure, |
| 6094 PropertyAttributes attributes) { | 6088 PropertyAttributes attributes) { |
| 6095 PropertyDetails details = PropertyDetails(attributes, CALLBACKS, 0); | 6089 PropertyDetails details = PropertyDetails(attributes, CALLBACKS, 0); |
| 6096 | 6090 |
| 6097 // Normalize elements to make this operation simple. | 6091 // Normalize elements to make this operation simple. |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6155 if (maybe_ok->IsFailure()) return maybe_ok; | 6149 if (maybe_ok->IsFailure()) return maybe_ok; |
| 6156 | 6150 |
| 6157 return GetHeap()->undefined_value(); | 6151 return GetHeap()->undefined_value(); |
| 6158 } | 6152 } |
| 6159 | 6153 |
| 6160 | 6154 |
| 6161 void JSObject::DefineAccessor(Handle<JSObject> object, | 6155 void JSObject::DefineAccessor(Handle<JSObject> object, |
| 6162 Handle<Name> name, | 6156 Handle<Name> name, |
| 6163 Handle<Object> getter, | 6157 Handle<Object> getter, |
| 6164 Handle<Object> setter, | 6158 Handle<Object> setter, |
| 6165 PropertyAttributes attributes) { | 6159 PropertyAttributes attributes, |
| 6160 v8::AccessControl access_control) { |
| 6166 Isolate* isolate = object->GetIsolate(); | 6161 Isolate* isolate = object->GetIsolate(); |
| 6167 // Check access rights if needed. | 6162 // Check access rights if needed. |
| 6168 if (object->IsAccessCheckNeeded() && | 6163 if (object->IsAccessCheckNeeded() && |
| 6169 !isolate->MayNamedAccess(*object, *name, v8::ACCESS_SET)) { | 6164 !isolate->MayNamedAccess(*object, *name, v8::ACCESS_SET)) { |
| 6170 isolate->ReportFailedAccessCheck(*object, v8::ACCESS_SET); | 6165 isolate->ReportFailedAccessCheck(*object, v8::ACCESS_SET); |
| 6171 return; | 6166 return; |
| 6172 } | 6167 } |
| 6173 | 6168 |
| 6174 if (object->IsJSGlobalProxy()) { | 6169 if (object->IsJSGlobalProxy()) { |
| 6175 Handle<Object> proto(object->GetPrototype(), isolate); | 6170 Handle<Object> proto(object->GetPrototype(), isolate); |
| 6176 if (proto->IsNull()) return; | 6171 if (proto->IsNull()) return; |
| 6177 ASSERT(proto->IsJSGlobalObject()); | 6172 ASSERT(proto->IsJSGlobalObject()); |
| 6178 DefineAccessor( | 6173 DefineAccessor(Handle<JSObject>::cast(proto), |
| 6179 Handle<JSObject>::cast(proto), name, getter, setter, attributes); | 6174 name, |
| 6175 getter, |
| 6176 setter, |
| 6177 attributes, |
| 6178 access_control); |
| 6180 return; | 6179 return; |
| 6181 } | 6180 } |
| 6182 | 6181 |
| 6183 // Make sure that the top context does not change when doing callbacks or | 6182 // Make sure that the top context does not change when doing callbacks or |
| 6184 // interceptor calls. | 6183 // interceptor calls. |
| 6185 AssertNoContextChange ncc; | 6184 AssertNoContextChange ncc; |
| 6186 | 6185 |
| 6187 // Try to flatten before operating on the string. | 6186 // Try to flatten before operating on the string. |
| 6188 if (name->IsString()) String::cast(*name)->TryFlatten(); | 6187 if (name->IsString()) String::cast(*name)->TryFlatten(); |
| 6189 | 6188 |
| (...skipping 15 matching lines...) Expand all Loading... |
| 6205 LookupResult lookup(isolate); | 6204 LookupResult lookup(isolate); |
| 6206 object->LocalLookup(*name, &lookup, true); | 6205 object->LocalLookup(*name, &lookup, true); |
| 6207 preexists = lookup.IsProperty(); | 6206 preexists = lookup.IsProperty(); |
| 6208 if (preexists && lookup.IsDataProperty()) { | 6207 if (preexists && lookup.IsDataProperty()) { |
| 6209 old_value = Object::GetProperty(object, name); | 6208 old_value = Object::GetProperty(object, name); |
| 6210 } | 6209 } |
| 6211 } | 6210 } |
| 6212 } | 6211 } |
| 6213 | 6212 |
| 6214 if (is_element) { | 6213 if (is_element) { |
| 6215 DefineElementAccessor(object, index, getter, setter, attributes); | 6214 DefineElementAccessor( |
| 6215 object, index, getter, setter, attributes, access_control); |
| 6216 } else { | 6216 } else { |
| 6217 DefinePropertyAccessor(object, name, getter, setter, attributes); | 6217 DefinePropertyAccessor( |
| 6218 object, name, getter, setter, attributes, access_control); |
| 6218 } | 6219 } |
| 6219 | 6220 |
| 6220 if (is_observed) { | 6221 if (is_observed) { |
| 6221 const char* type = preexists ? "reconfigured" : "new"; | 6222 const char* type = preexists ? "reconfigured" : "new"; |
| 6222 EnqueueChangeRecord(object, type, name, old_value); | 6223 EnqueueChangeRecord(object, type, name, old_value); |
| 6223 } | 6224 } |
| 6224 } | 6225 } |
| 6225 | 6226 |
| 6226 | 6227 |
| 6227 static bool TryAccessorTransition(JSObject* self, | 6228 static bool TryAccessorTransition(JSObject* self, |
| (...skipping 440 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6668 if (!maybe_result->To(&result)) return maybe_result; | 6669 if (!maybe_result->To(&result)) return maybe_result; |
| 6669 | 6670 |
| 6670 result->InitializeDescriptors(descriptors); | 6671 result->InitializeDescriptors(descriptors); |
| 6671 | 6672 |
| 6672 if (flag == INSERT_TRANSITION && CanHaveMoreTransitions()) { | 6673 if (flag == INSERT_TRANSITION && CanHaveMoreTransitions()) { |
| 6673 TransitionArray* transitions; | 6674 TransitionArray* transitions; |
| 6674 MaybeObject* maybe_transitions = AddTransition(name, result, simple_flag); | 6675 MaybeObject* maybe_transitions = AddTransition(name, result, simple_flag); |
| 6675 if (!maybe_transitions->To(&transitions)) return maybe_transitions; | 6676 if (!maybe_transitions->To(&transitions)) return maybe_transitions; |
| 6676 set_transitions(transitions); | 6677 set_transitions(transitions); |
| 6677 result->SetBackPointer(this); | 6678 result->SetBackPointer(this); |
| 6678 } else if (flag != OMIT_TRANSITION_KEEP_REPRESENTATIONS) { | 6679 } else { |
| 6679 descriptors->InitializeRepresentations(Representation::Tagged()); | 6680 descriptors->InitializeRepresentations(Representation::Tagged()); |
| 6680 } | 6681 } |
| 6681 | 6682 |
| 6682 return result; | 6683 return result; |
| 6683 } | 6684 } |
| 6684 | 6685 |
| 6685 | 6686 |
| 6686 // Since this method is used to rewrite an existing transition tree, it can | 6687 // Since this method is used to rewrite an existing transition tree, it can |
| 6687 // always insert transitions without checking. | 6688 // always insert transitions without checking. |
| 6688 MaybeObject* Map::CopyInstallDescriptors(int new_descriptor, | 6689 MaybeObject* Map::CopyInstallDescriptors(int new_descriptor, |
| (...skipping 1107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7796 // The method merges two descriptor array in three parts. Both descriptor arrays | 7797 // The method merges two descriptor array in three parts. Both descriptor arrays |
| 7797 // are identical up to |verbatim|. They also overlap in keys up to |valid|. | 7798 // are identical up to |verbatim|. They also overlap in keys up to |valid|. |
| 7798 // Between |verbatim| and |valid|, the resulting descriptor type as well as the | 7799 // Between |verbatim| and |valid|, the resulting descriptor type as well as the |
| 7799 // representation are generalized from both |this| and |other|. Beyond |valid|, | 7800 // representation are generalized from both |this| and |other|. Beyond |valid|, |
| 7800 // the descriptors are copied verbatim from |other| up to |new_size|. | 7801 // the descriptors are copied verbatim from |other| up to |new_size|. |
| 7801 // In case of incompatible types, the type and representation of |other| is | 7802 // In case of incompatible types, the type and representation of |other| is |
| 7802 // used. | 7803 // used. |
| 7803 MaybeObject* DescriptorArray::Merge(int verbatim, | 7804 MaybeObject* DescriptorArray::Merge(int verbatim, |
| 7804 int valid, | 7805 int valid, |
| 7805 int new_size, | 7806 int new_size, |
| 7807 int modify_index, |
| 7808 StoreMode store_mode, |
| 7806 DescriptorArray* other) { | 7809 DescriptorArray* other) { |
| 7807 ASSERT(verbatim <= valid); | 7810 ASSERT(verbatim <= valid); |
| 7808 ASSERT(valid <= new_size); | 7811 ASSERT(valid <= new_size); |
| 7809 | 7812 |
| 7810 DescriptorArray* result; | 7813 DescriptorArray* result; |
| 7811 // Allocate a new descriptor array large enough to hold the required | 7814 // Allocate a new descriptor array large enough to hold the required |
| 7812 // descriptors, with minimally the exact same size as this descriptor array. | 7815 // descriptors, with minimally the exact same size as this descriptor array. |
| 7813 MaybeObject* maybe_descriptors = DescriptorArray::Allocate( | 7816 MaybeObject* maybe_descriptors = DescriptorArray::Allocate( |
| 7814 new_size, Max(new_size, other->number_of_descriptors()) - new_size); | 7817 new_size, Max(new_size, other->number_of_descriptors()) - new_size); |
| 7815 if (!maybe_descriptors->To(&result)) return maybe_descriptors; | 7818 if (!maybe_descriptors->To(&result)) return maybe_descriptors; |
| (...skipping 13 matching lines...) Expand all Loading... |
| 7829 result->CopyFrom(descriptor, this, descriptor, witness); | 7832 result->CopyFrom(descriptor, this, descriptor, witness); |
| 7830 } | 7833 } |
| 7831 | 7834 |
| 7832 // |verbatim| -> |valid| | 7835 // |verbatim| -> |valid| |
| 7833 for (; descriptor < valid; descriptor++) { | 7836 for (; descriptor < valid; descriptor++) { |
| 7834 Name* key = GetKey(descriptor); | 7837 Name* key = GetKey(descriptor); |
| 7835 PropertyDetails details = GetDetails(descriptor); | 7838 PropertyDetails details = GetDetails(descriptor); |
| 7836 PropertyDetails other_details = other->GetDetails(descriptor); | 7839 PropertyDetails other_details = other->GetDetails(descriptor); |
| 7837 | 7840 |
| 7838 if (details.type() == FIELD || other_details.type() == FIELD || | 7841 if (details.type() == FIELD || other_details.type() == FIELD || |
| 7842 (store_mode == FORCE_FIELD && descriptor == modify_index) || |
| 7839 (details.type() == CONSTANT && | 7843 (details.type() == CONSTANT && |
| 7840 other_details.type() == CONSTANT && | 7844 other_details.type() == CONSTANT && |
| 7841 GetValue(descriptor) != other->GetValue(descriptor))) { | 7845 GetValue(descriptor) != other->GetValue(descriptor))) { |
| 7842 Representation representation = | 7846 Representation representation = |
| 7843 details.representation().generalize(other_details.representation()); | 7847 details.representation().generalize(other_details.representation()); |
| 7844 FieldDescriptor d(key, | 7848 FieldDescriptor d(key, |
| 7845 current_offset++, | 7849 current_offset++, |
| 7846 other_details.attributes(), | 7850 other_details.attributes(), |
| 7847 representation); | 7851 representation); |
| 7848 result->Set(descriptor, &d, witness); | 7852 result->Set(descriptor, &d, witness); |
| 7849 } else { | 7853 } else { |
| 7850 result->CopyFrom(descriptor, other, descriptor, witness); | 7854 result->CopyFrom(descriptor, other, descriptor, witness); |
| 7851 } | 7855 } |
| 7852 } | 7856 } |
| 7853 | 7857 |
| 7854 // |valid| -> |new_size| | 7858 // |valid| -> |new_size| |
| 7855 for (; descriptor < new_size; descriptor++) { | 7859 for (; descriptor < new_size; descriptor++) { |
| 7856 PropertyDetails details = other->GetDetails(descriptor); | 7860 PropertyDetails details = other->GetDetails(descriptor); |
| 7857 if (details.type() == FIELD) { | 7861 if (details.type() == FIELD || |
| 7862 (store_mode == FORCE_FIELD && descriptor == modify_index)) { |
| 7858 Name* key = other->GetKey(descriptor); | 7863 Name* key = other->GetKey(descriptor); |
| 7859 FieldDescriptor d(key, | 7864 FieldDescriptor d(key, |
| 7860 current_offset++, | 7865 current_offset++, |
| 7861 details.attributes(), | 7866 details.attributes(), |
| 7862 details.representation()); | 7867 details.representation()); |
| 7863 result->Set(descriptor, &d, witness); | 7868 result->Set(descriptor, &d, witness); |
| 7864 } else { | 7869 } else { |
| 7865 result->CopyFrom(descriptor, other, descriptor, witness); | 7870 result->CopyFrom(descriptor, other, descriptor, witness); |
| 7866 } | 7871 } |
| 7867 } | 7872 } |
| (...skipping 1384 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9252 ASSERT(!IsOptimized()); | 9257 ASSERT(!IsOptimized()); |
| 9253 ASSERT(shared()->allows_lazy_compilation() || | 9258 ASSERT(shared()->allows_lazy_compilation() || |
| 9254 code()->optimizable()); | 9259 code()->optimizable()); |
| 9255 ASSERT(!shared()->is_generator()); | 9260 ASSERT(!shared()->is_generator()); |
| 9256 set_code_no_write_barrier( | 9261 set_code_no_write_barrier( |
| 9257 GetIsolate()->builtins()->builtin(Builtins::kLazyRecompile)); | 9262 GetIsolate()->builtins()->builtin(Builtins::kLazyRecompile)); |
| 9258 // No write barrier required, since the builtin is part of the root set. | 9263 // No write barrier required, since the builtin is part of the root set. |
| 9259 } | 9264 } |
| 9260 | 9265 |
| 9261 | 9266 |
| 9262 void JSFunction::MarkForParallelRecompilation() { | 9267 void JSFunction::MarkForConcurrentRecompilation() { |
| 9263 ASSERT(is_compiled() || GetIsolate()->DebuggerHasBreakPoints()); | 9268 ASSERT(is_compiled() || GetIsolate()->DebuggerHasBreakPoints()); |
| 9264 ASSERT(!IsOptimized()); | 9269 ASSERT(!IsOptimized()); |
| 9265 ASSERT(shared()->allows_lazy_compilation() || code()->optimizable()); | 9270 ASSERT(shared()->allows_lazy_compilation() || code()->optimizable()); |
| 9266 ASSERT(!shared()->is_generator()); | 9271 ASSERT(!shared()->is_generator()); |
| 9267 ASSERT(FLAG_parallel_recompilation); | 9272 ASSERT(FLAG_concurrent_recompilation); |
| 9268 if (FLAG_trace_parallel_recompilation) { | 9273 if (FLAG_trace_concurrent_recompilation) { |
| 9269 PrintF(" ** Marking "); | 9274 PrintF(" ** Marking "); |
| 9270 PrintName(); | 9275 PrintName(); |
| 9271 PrintF(" for parallel recompilation.\n"); | 9276 PrintF(" for concurrent recompilation.\n"); |
| 9272 } | 9277 } |
| 9273 set_code_no_write_barrier( | 9278 set_code_no_write_barrier( |
| 9274 GetIsolate()->builtins()->builtin(Builtins::kParallelRecompile)); | 9279 GetIsolate()->builtins()->builtin(Builtins::kConcurrentRecompile)); |
| 9275 // No write barrier required, since the builtin is part of the root set. | 9280 // No write barrier required, since the builtin is part of the root set. |
| 9276 } | 9281 } |
| 9277 | 9282 |
| 9278 | 9283 |
| 9279 void JSFunction::MarkForInstallingRecompiledCode() { | 9284 void JSFunction::MarkForInstallingRecompiledCode() { |
| 9280 // The debugger could have switched the builtin to lazy compile. | 9285 // The debugger could have switched the builtin to lazy compile. |
| 9281 // In that case, simply carry on. It will be dealt with later. | 9286 // In that case, simply carry on. It will be dealt with later. |
| 9282 ASSERT(!IsOptimized()); | 9287 ASSERT(!IsOptimized()); |
| 9283 ASSERT(shared()->allows_lazy_compilation() || code()->optimizable()); | 9288 ASSERT(shared()->allows_lazy_compilation() || code()->optimizable()); |
| 9284 ASSERT(FLAG_parallel_recompilation); | 9289 ASSERT(FLAG_concurrent_recompilation); |
| 9285 set_code_no_write_barrier( | 9290 set_code_no_write_barrier( |
| 9286 GetIsolate()->builtins()->builtin(Builtins::kInstallRecompiledCode)); | 9291 GetIsolate()->builtins()->builtin(Builtins::kInstallRecompiledCode)); |
| 9287 // No write barrier required, since the builtin is part of the root set. | 9292 // No write barrier required, since the builtin is part of the root set. |
| 9288 } | 9293 } |
| 9289 | 9294 |
| 9290 | 9295 |
| 9291 void JSFunction::MarkInRecompileQueue() { | 9296 void JSFunction::MarkInRecompileQueue() { |
| 9292 // We can only arrive here via the parallel-recompilation builtin. If | 9297 // We can only arrive here via the concurrent-recompilation builtin. If |
| 9293 // break points were set, the code would point to the lazy-compile builtin. | 9298 // break points were set, the code would point to the lazy-compile builtin. |
| 9294 ASSERT(!GetIsolate()->DebuggerHasBreakPoints()); | 9299 ASSERT(!GetIsolate()->DebuggerHasBreakPoints()); |
| 9295 ASSERT(IsMarkedForParallelRecompilation() && !IsOptimized()); | 9300 ASSERT(IsMarkedForConcurrentRecompilation() && !IsOptimized()); |
| 9296 ASSERT(shared()->allows_lazy_compilation() || code()->optimizable()); | 9301 ASSERT(shared()->allows_lazy_compilation() || code()->optimizable()); |
| 9297 ASSERT(FLAG_parallel_recompilation); | 9302 ASSERT(FLAG_concurrent_recompilation); |
| 9298 if (FLAG_trace_parallel_recompilation) { | 9303 if (FLAG_trace_concurrent_recompilation) { |
| 9299 PrintF(" ** Queueing "); | 9304 PrintF(" ** Queueing "); |
| 9300 PrintName(); | 9305 PrintName(); |
| 9301 PrintF(" for parallel recompilation.\n"); | 9306 PrintF(" for concurrent recompilation.\n"); |
| 9302 } | 9307 } |
| 9303 set_code_no_write_barrier( | 9308 set_code_no_write_barrier( |
| 9304 GetIsolate()->builtins()->builtin(Builtins::kInRecompileQueue)); | 9309 GetIsolate()->builtins()->builtin(Builtins::kInRecompileQueue)); |
| 9305 // No write barrier required, since the builtin is part of the root set. | 9310 // No write barrier required, since the builtin is part of the root set. |
| 9306 } | 9311 } |
| 9307 | 9312 |
| 9308 | 9313 |
| 9309 static bool CompileLazyHelper(CompilationInfo* info, | 9314 static bool CompileLazyHelper(CompilationInfo* info, |
| 9310 ClearExceptionFlag flag) { | 9315 ClearExceptionFlag flag) { |
| 9311 // Compile the source information to a code object. | 9316 // Compile the source information to a code object. |
| (...skipping 358 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9670 SmartArrayPointer<char> name = shared()->DebugName()->ToCString(); | 9675 SmartArrayPointer<char> name = shared()->DebugName()->ToCString(); |
| 9671 PrintF(out, "%s", *name); | 9676 PrintF(out, "%s", *name); |
| 9672 } | 9677 } |
| 9673 | 9678 |
| 9674 | 9679 |
| 9675 Context* JSFunction::NativeContextFromLiterals(FixedArray* literals) { | 9680 Context* JSFunction::NativeContextFromLiterals(FixedArray* literals) { |
| 9676 return Context::cast(literals->get(JSFunction::kLiteralNativeContextIndex)); | 9681 return Context::cast(literals->get(JSFunction::kLiteralNativeContextIndex)); |
| 9677 } | 9682 } |
| 9678 | 9683 |
| 9679 | 9684 |
| 9680 bool JSFunction::PassesHydrogenFilter() { | 9685 // The filter is a pattern that matches function names in this way: |
| 9686 // "*" all; the default |
| 9687 // "-" all but the top-level function |
| 9688 // "-name" all but the function "name" |
| 9689 // "" only the top-level function |
| 9690 // "name" only the function "name" |
| 9691 // "name*" only functions starting with "name" |
| 9692 bool JSFunction::PassesFilter(const char* raw_filter) { |
| 9693 if (*raw_filter == '*') return true; |
| 9681 String* name = shared()->DebugName(); | 9694 String* name = shared()->DebugName(); |
| 9682 // The filter string is a pattern that matches functions in this way: | 9695 Vector<const char> filter = CStrVector(raw_filter); |
| 9683 // "*" all; the default | 9696 if (filter.length() == 0) return name->length() == 0; |
| 9684 // "-" all but the top-level function | 9697 if (filter[0] != '-' && name->IsUtf8EqualTo(filter)) return true; |
| 9685 // "-name" all but the function "name" | 9698 if (filter[0] == '-' && |
| 9686 // "" only the top-level function | 9699 !name->IsUtf8EqualTo(filter.SubVector(1, filter.length()))) { |
| 9687 // "name" only the function "name" | 9700 return true; |
| 9688 // "name*" only functions starting with "name" | |
| 9689 if (*FLAG_hydrogen_filter != '*') { | |
| 9690 Vector<const char> filter = CStrVector(FLAG_hydrogen_filter); | |
| 9691 if (filter.length() == 0) return name->length() == 0; | |
| 9692 if (filter[0] != '-' && name->IsUtf8EqualTo(filter)) return true; | |
| 9693 if (filter[0] == '-' && | |
| 9694 !name->IsUtf8EqualTo(filter.SubVector(1, filter.length()))) { | |
| 9695 return true; | |
| 9696 } | |
| 9697 if (filter[filter.length() - 1] == '*' && | |
| 9698 name->IsUtf8EqualTo(filter.SubVector(0, filter.length() - 1), true)) { | |
| 9699 return true; | |
| 9700 } | |
| 9701 return false; | |
| 9702 } | 9701 } |
| 9703 | 9702 if (filter[filter.length() - 1] == '*' && |
| 9704 return true; | 9703 name->IsUtf8EqualTo(filter.SubVector(0, filter.length() - 1), true)) { |
| 9704 return true; |
| 9705 } |
| 9706 return false; |
| 9705 } | 9707 } |
| 9706 | 9708 |
| 9707 | 9709 |
| 9708 MaybeObject* Oddball::Initialize(const char* to_string, | 9710 MaybeObject* Oddball::Initialize(const char* to_string, |
| 9709 Object* to_number, | 9711 Object* to_number, |
| 9710 byte kind) { | 9712 byte kind) { |
| 9711 String* internalized_to_string; | 9713 String* internalized_to_string; |
| 9712 { MaybeObject* maybe_string = | 9714 { MaybeObject* maybe_string = |
| 9713 Isolate::Current()->heap()->InternalizeUtf8String( | 9715 Isolate::Current()->heap()->InternalizeUtf8String( |
| 9714 CStrVector(to_string)); | 9716 CStrVector(to_string)); |
| (...skipping 1855 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 11570 SetPropertyMode set_mode) { | 11572 SetPropertyMode set_mode) { |
| 11571 Isolate* isolate = GetIsolate(); | 11573 Isolate* isolate = GetIsolate(); |
| 11572 // Make sure that the top context does not change when doing | 11574 // Make sure that the top context does not change when doing |
| 11573 // callbacks or interceptor calls. | 11575 // callbacks or interceptor calls. |
| 11574 AssertNoContextChange ncc; | 11576 AssertNoContextChange ncc; |
| 11575 HandleScope scope(isolate); | 11577 HandleScope scope(isolate); |
| 11576 Handle<InterceptorInfo> interceptor(GetIndexedInterceptor()); | 11578 Handle<InterceptorInfo> interceptor(GetIndexedInterceptor()); |
| 11577 Handle<JSObject> this_handle(this); | 11579 Handle<JSObject> this_handle(this); |
| 11578 Handle<Object> value_handle(value, isolate); | 11580 Handle<Object> value_handle(value, isolate); |
| 11579 if (!interceptor->setter()->IsUndefined()) { | 11581 if (!interceptor->setter()->IsUndefined()) { |
| 11580 v8::IndexedPropertySetter setter = | 11582 v8::IndexedPropertySetterCallback setter = |
| 11581 v8::ToCData<v8::IndexedPropertySetter>(interceptor->setter()); | 11583 v8::ToCData<v8::IndexedPropertySetterCallback>(interceptor->setter()); |
| 11582 LOG(isolate, | 11584 LOG(isolate, |
| 11583 ApiIndexedPropertyAccess("interceptor-indexed-set", this, index)); | 11585 ApiIndexedPropertyAccess("interceptor-indexed-set", this, index)); |
| 11584 PropertyCallbackArguments args(isolate, interceptor->data(), this, this); | 11586 PropertyCallbackArguments args(isolate, interceptor->data(), this, this); |
| 11585 v8::Handle<v8::Value> result = | 11587 v8::Handle<v8::Value> result = |
| 11586 args.Call(setter, index, v8::Utils::ToLocal(value_handle)); | 11588 args.Call(setter, index, v8::Utils::ToLocal(value_handle)); |
| 11587 RETURN_IF_SCHEDULED_EXCEPTION(isolate); | 11589 RETURN_IF_SCHEDULED_EXCEPTION(isolate); |
| 11588 if (!result.IsEmpty()) return *value_handle; | 11590 if (!result.IsEmpty()) return *value_handle; |
| 11589 } | 11591 } |
| 11590 MaybeObject* raw_result = | 11592 MaybeObject* raw_result = |
| 11591 this_handle->SetElementWithoutInterceptor(index, | 11593 this_handle->SetElementWithoutInterceptor(index, |
| (...skipping 12 matching lines...) Expand all Loading... |
| 11604 uint32_t index, | 11606 uint32_t index, |
| 11605 Object* holder) { | 11607 Object* holder) { |
| 11606 Isolate* isolate = GetIsolate(); | 11608 Isolate* isolate = GetIsolate(); |
| 11607 ASSERT(!structure->IsForeign()); | 11609 ASSERT(!structure->IsForeign()); |
| 11608 | 11610 |
| 11609 // api style callbacks. | 11611 // api style callbacks. |
| 11610 if (structure->IsExecutableAccessorInfo()) { | 11612 if (structure->IsExecutableAccessorInfo()) { |
| 11611 Handle<ExecutableAccessorInfo> data( | 11613 Handle<ExecutableAccessorInfo> data( |
| 11612 ExecutableAccessorInfo::cast(structure)); | 11614 ExecutableAccessorInfo::cast(structure)); |
| 11613 Object* fun_obj = data->getter(); | 11615 Object* fun_obj = data->getter(); |
| 11614 v8::AccessorGetter call_fun = v8::ToCData<v8::AccessorGetter>(fun_obj); | 11616 v8::AccessorGetterCallback call_fun = |
| 11617 v8::ToCData<v8::AccessorGetterCallback>(fun_obj); |
| 11615 if (call_fun == NULL) return isolate->heap()->undefined_value(); | 11618 if (call_fun == NULL) return isolate->heap()->undefined_value(); |
| 11616 HandleScope scope(isolate); | 11619 HandleScope scope(isolate); |
| 11617 Handle<JSObject> self(JSObject::cast(receiver)); | 11620 Handle<JSObject> self(JSObject::cast(receiver)); |
| 11618 Handle<JSObject> holder_handle(JSObject::cast(holder)); | 11621 Handle<JSObject> holder_handle(JSObject::cast(holder)); |
| 11619 Handle<Object> number = isolate->factory()->NewNumberFromUint(index); | 11622 Handle<Object> number = isolate->factory()->NewNumberFromUint(index); |
| 11620 Handle<String> key = isolate->factory()->NumberToString(number); | 11623 Handle<String> key = isolate->factory()->NumberToString(number); |
| 11621 LOG(isolate, ApiNamedPropertyAccess("load", *self, *key)); | 11624 LOG(isolate, ApiNamedPropertyAccess("load", *self, *key)); |
| 11622 PropertyCallbackArguments | 11625 PropertyCallbackArguments |
| 11623 args(isolate, data->data(), *self, *holder_handle); | 11626 args(isolate, data->data(), *self, *holder_handle); |
| 11624 v8::Handle<v8::Value> result = args.Call(call_fun, v8::Utils::ToLocal(key)); | 11627 v8::Handle<v8::Value> result = args.Call(call_fun, v8::Utils::ToLocal(key)); |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 11669 // callbacks should be phased out. | 11672 // callbacks should be phased out. |
| 11670 ASSERT(!structure->IsForeign()); | 11673 ASSERT(!structure->IsForeign()); |
| 11671 | 11674 |
| 11672 if (structure->IsExecutableAccessorInfo()) { | 11675 if (structure->IsExecutableAccessorInfo()) { |
| 11673 // api style callbacks | 11676 // api style callbacks |
| 11674 Handle<JSObject> self(this); | 11677 Handle<JSObject> self(this); |
| 11675 Handle<JSObject> holder_handle(JSObject::cast(holder)); | 11678 Handle<JSObject> holder_handle(JSObject::cast(holder)); |
| 11676 Handle<ExecutableAccessorInfo> data( | 11679 Handle<ExecutableAccessorInfo> data( |
| 11677 ExecutableAccessorInfo::cast(structure)); | 11680 ExecutableAccessorInfo::cast(structure)); |
| 11678 Object* call_obj = data->setter(); | 11681 Object* call_obj = data->setter(); |
| 11679 v8::AccessorSetter call_fun = v8::ToCData<v8::AccessorSetter>(call_obj); | 11682 v8::AccessorSetterCallback call_fun = |
| 11683 v8::ToCData<v8::AccessorSetterCallback>(call_obj); |
| 11680 if (call_fun == NULL) return value; | 11684 if (call_fun == NULL) return value; |
| 11681 Handle<Object> number = isolate->factory()->NewNumberFromUint(index); | 11685 Handle<Object> number = isolate->factory()->NewNumberFromUint(index); |
| 11682 Handle<String> key(isolate->factory()->NumberToString(number)); | 11686 Handle<String> key(isolate->factory()->NumberToString(number)); |
| 11683 LOG(isolate, ApiNamedPropertyAccess("store", *self, *key)); | 11687 LOG(isolate, ApiNamedPropertyAccess("store", *self, *key)); |
| 11684 PropertyCallbackArguments | 11688 PropertyCallbackArguments |
| 11685 args(isolate, data->data(), *self, *holder_handle); | 11689 args(isolate, data->data(), *self, *holder_handle); |
| 11686 args.Call(call_fun, | 11690 args.Call(call_fun, |
| 11687 v8::Utils::ToLocal(key), | 11691 v8::Utils::ToLocal(key), |
| 11688 v8::Utils::ToLocal(value_handle)); | 11692 v8::Utils::ToLocal(value_handle)); |
| 11689 RETURN_IF_SCHEDULED_EXCEPTION(isolate); | 11693 RETURN_IF_SCHEDULED_EXCEPTION(isolate); |
| (...skipping 888 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 12578 uint32_t index) { | 12582 uint32_t index) { |
| 12579 Isolate* isolate = GetIsolate(); | 12583 Isolate* isolate = GetIsolate(); |
| 12580 // Make sure that the top context does not change when doing | 12584 // Make sure that the top context does not change when doing |
| 12581 // callbacks or interceptor calls. | 12585 // callbacks or interceptor calls. |
| 12582 AssertNoContextChange ncc; | 12586 AssertNoContextChange ncc; |
| 12583 HandleScope scope(isolate); | 12587 HandleScope scope(isolate); |
| 12584 Handle<InterceptorInfo> interceptor(GetIndexedInterceptor(), isolate); | 12588 Handle<InterceptorInfo> interceptor(GetIndexedInterceptor(), isolate); |
| 12585 Handle<Object> this_handle(receiver, isolate); | 12589 Handle<Object> this_handle(receiver, isolate); |
| 12586 Handle<JSObject> holder_handle(this, isolate); | 12590 Handle<JSObject> holder_handle(this, isolate); |
| 12587 if (!interceptor->getter()->IsUndefined()) { | 12591 if (!interceptor->getter()->IsUndefined()) { |
| 12588 v8::IndexedPropertyGetter getter = | 12592 v8::IndexedPropertyGetterCallback getter = |
| 12589 v8::ToCData<v8::IndexedPropertyGetter>(interceptor->getter()); | 12593 v8::ToCData<v8::IndexedPropertyGetterCallback>(interceptor->getter()); |
| 12590 LOG(isolate, | 12594 LOG(isolate, |
| 12591 ApiIndexedPropertyAccess("interceptor-indexed-get", this, index)); | 12595 ApiIndexedPropertyAccess("interceptor-indexed-get", this, index)); |
| 12592 PropertyCallbackArguments | 12596 PropertyCallbackArguments |
| 12593 args(isolate, interceptor->data(), receiver, this); | 12597 args(isolate, interceptor->data(), receiver, this); |
| 12594 v8::Handle<v8::Value> result = args.Call(getter, index); | 12598 v8::Handle<v8::Value> result = args.Call(getter, index); |
| 12595 RETURN_IF_SCHEDULED_EXCEPTION(isolate); | 12599 RETURN_IF_SCHEDULED_EXCEPTION(isolate); |
| 12596 if (!result.IsEmpty()) { | 12600 if (!result.IsEmpty()) { |
| 12597 Handle<Object> result_internal = v8::Utils::OpenHandle(*result); | 12601 Handle<Object> result_internal = v8::Utils::OpenHandle(*result); |
| 12598 result_internal->VerifyApiCallResultType(); | 12602 result_internal->VerifyApiCallResultType(); |
| 12599 return *result_internal; | 12603 return *result_internal; |
| (...skipping 283 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 12883 if (name->IsSymbol()) return GetHeap()->undefined_value(); | 12887 if (name->IsSymbol()) return GetHeap()->undefined_value(); |
| 12884 | 12888 |
| 12885 Isolate* isolate = GetIsolate(); | 12889 Isolate* isolate = GetIsolate(); |
| 12886 InterceptorInfo* interceptor = GetNamedInterceptor(); | 12890 InterceptorInfo* interceptor = GetNamedInterceptor(); |
| 12887 HandleScope scope(isolate); | 12891 HandleScope scope(isolate); |
| 12888 Handle<Object> receiver_handle(receiver, isolate); | 12892 Handle<Object> receiver_handle(receiver, isolate); |
| 12889 Handle<JSObject> holder_handle(this); | 12893 Handle<JSObject> holder_handle(this); |
| 12890 Handle<String> name_handle(String::cast(name)); | 12894 Handle<String> name_handle(String::cast(name)); |
| 12891 | 12895 |
| 12892 if (!interceptor->getter()->IsUndefined()) { | 12896 if (!interceptor->getter()->IsUndefined()) { |
| 12893 v8::NamedPropertyGetter getter = | 12897 v8::NamedPropertyGetterCallback getter = |
| 12894 v8::ToCData<v8::NamedPropertyGetter>(interceptor->getter()); | 12898 v8::ToCData<v8::NamedPropertyGetterCallback>(interceptor->getter()); |
| 12895 LOG(isolate, | 12899 LOG(isolate, |
| 12896 ApiNamedPropertyAccess("interceptor-named-get", *holder_handle, name)); | 12900 ApiNamedPropertyAccess("interceptor-named-get", *holder_handle, name)); |
| 12897 PropertyCallbackArguments | 12901 PropertyCallbackArguments |
| 12898 args(isolate, interceptor->data(), receiver, this); | 12902 args(isolate, interceptor->data(), receiver, this); |
| 12899 v8::Handle<v8::Value> result = | 12903 v8::Handle<v8::Value> result = |
| 12900 args.Call(getter, v8::Utils::ToLocal(name_handle)); | 12904 args.Call(getter, v8::Utils::ToLocal(name_handle)); |
| 12901 RETURN_IF_SCHEDULED_EXCEPTION(isolate); | 12905 RETURN_IF_SCHEDULED_EXCEPTION(isolate); |
| 12902 if (!result.IsEmpty()) { | 12906 if (!result.IsEmpty()) { |
| 12903 *attributes = NONE; | 12907 *attributes = NONE; |
| 12904 Handle<Object> result_internal = v8::Utils::OpenHandle(*result); | 12908 Handle<Object> result_internal = v8::Utils::OpenHandle(*result); |
| (...skipping 2451 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 15356 } | 15360 } |
| 15357 | 15361 |
| 15358 | 15362 |
| 15359 MaybeObject* ObjectHashSet::Add(Object* key) { | 15363 MaybeObject* ObjectHashSet::Add(Object* key) { |
| 15360 ASSERT(IsKey(key)); | 15364 ASSERT(IsKey(key)); |
| 15361 | 15365 |
| 15362 // Make sure the key object has an identity hash code. | 15366 // Make sure the key object has an identity hash code. |
| 15363 int hash; | 15367 int hash; |
| 15364 { MaybeObject* maybe_hash = key->GetHash(ALLOW_CREATION); | 15368 { MaybeObject* maybe_hash = key->GetHash(ALLOW_CREATION); |
| 15365 if (maybe_hash->IsFailure()) return maybe_hash; | 15369 if (maybe_hash->IsFailure()) return maybe_hash; |
| 15370 ASSERT(key->GetHash(OMIT_CREATION) == maybe_hash); |
| 15366 hash = Smi::cast(maybe_hash->ToObjectUnchecked())->value(); | 15371 hash = Smi::cast(maybe_hash->ToObjectUnchecked())->value(); |
| 15367 } | 15372 } |
| 15368 int entry = FindEntry(key); | 15373 int entry = FindEntry(key); |
| 15369 | 15374 |
| 15370 // Check whether key is already present. | 15375 // Check whether key is already present. |
| 15371 if (entry != kNotFound) return this; | 15376 if (entry != kNotFound) return this; |
| 15372 | 15377 |
| 15373 // Check whether the hash set should be extended and add entry. | 15378 // Check whether the hash set should be extended and add entry. |
| 15374 Object* obj; | 15379 Object* obj; |
| 15375 { MaybeObject* maybe_obj = EnsureCapacity(1, key); | 15380 { MaybeObject* maybe_obj = EnsureCapacity(1, key); |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 15417 } | 15422 } |
| 15418 | 15423 |
| 15419 | 15424 |
| 15420 MaybeObject* ObjectHashTable::Put(Object* key, Object* value) { | 15425 MaybeObject* ObjectHashTable::Put(Object* key, Object* value) { |
| 15421 ASSERT(IsKey(key)); | 15426 ASSERT(IsKey(key)); |
| 15422 | 15427 |
| 15423 // Make sure the key object has an identity hash code. | 15428 // Make sure the key object has an identity hash code. |
| 15424 int hash; | 15429 int hash; |
| 15425 { MaybeObject* maybe_hash = key->GetHash(ALLOW_CREATION); | 15430 { MaybeObject* maybe_hash = key->GetHash(ALLOW_CREATION); |
| 15426 if (maybe_hash->IsFailure()) return maybe_hash; | 15431 if (maybe_hash->IsFailure()) return maybe_hash; |
| 15432 ASSERT(key->GetHash(OMIT_CREATION) == maybe_hash); |
| 15427 hash = Smi::cast(maybe_hash->ToObjectUnchecked())->value(); | 15433 hash = Smi::cast(maybe_hash->ToObjectUnchecked())->value(); |
| 15428 } | 15434 } |
| 15429 int entry = FindEntry(key); | 15435 int entry = FindEntry(key); |
| 15430 | 15436 |
| 15431 // Check whether to perform removal operation. | 15437 // Check whether to perform removal operation. |
| 15432 if (value->IsTheHole()) { | 15438 if (value->IsTheHole()) { |
| 15433 if (entry == kNotFound) return this; | 15439 if (entry == kNotFound) return this; |
| 15434 RemoveEntry(entry); | 15440 RemoveEntry(entry); |
| 15435 return Shrink(key); | 15441 return Shrink(key); |
| 15436 } | 15442 } |
| (...skipping 570 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 16007 #define ERROR_MESSAGES_TEXTS(C, T) T, | 16013 #define ERROR_MESSAGES_TEXTS(C, T) T, |
| 16008 static const char* error_messages_[] = { | 16014 static const char* error_messages_[] = { |
| 16009 ERROR_MESSAGES_LIST(ERROR_MESSAGES_TEXTS) | 16015 ERROR_MESSAGES_LIST(ERROR_MESSAGES_TEXTS) |
| 16010 }; | 16016 }; |
| 16011 #undef ERROR_MESSAGES_TEXTS | 16017 #undef ERROR_MESSAGES_TEXTS |
| 16012 return error_messages_[reason]; | 16018 return error_messages_[reason]; |
| 16013 } | 16019 } |
| 16014 | 16020 |
| 16015 | 16021 |
| 16016 } } // namespace v8::internal | 16022 } } // namespace v8::internal |
| OLD | NEW |