| OLD | NEW |
| 1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 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 1426 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1437 } | 1437 } |
| 1438 } | 1438 } |
| 1439 } | 1439 } |
| 1440 return AddSlowProperty(name, value, attributes); | 1440 return AddSlowProperty(name, value, attributes); |
| 1441 } | 1441 } |
| 1442 | 1442 |
| 1443 | 1443 |
| 1444 MaybeObject* JSObject::SetPropertyPostInterceptor( | 1444 MaybeObject* JSObject::SetPropertyPostInterceptor( |
| 1445 String* name, | 1445 String* name, |
| 1446 Object* value, | 1446 Object* value, |
| 1447 PropertyAttributes attributes) { | 1447 PropertyAttributes attributes, |
| 1448 StrictModeFlag strict) { |
| 1448 // Check local property, ignore interceptor. | 1449 // Check local property, ignore interceptor. |
| 1449 LookupResult result; | 1450 LookupResult result; |
| 1450 LocalLookupRealNamedProperty(name, &result); | 1451 LocalLookupRealNamedProperty(name, &result); |
| 1451 if (result.IsFound()) { | 1452 if (result.IsFound()) { |
| 1452 // An existing property, a map transition or a null descriptor was | 1453 // An existing property, a map transition or a null descriptor was |
| 1453 // found. Use set property to handle all these cases. | 1454 // found. Use set property to handle all these cases. |
| 1454 return SetProperty(&result, name, value, attributes); | 1455 return SetProperty(&result, name, value, attributes, strict); |
| 1455 } | 1456 } |
| 1456 // Add a new real property. | 1457 // Add a new real property. |
| 1457 return AddProperty(name, value, attributes); | 1458 return AddProperty(name, value, attributes); |
| 1458 } | 1459 } |
| 1459 | 1460 |
| 1460 | 1461 |
| 1461 MaybeObject* JSObject::ReplaceSlowProperty(String* name, | 1462 MaybeObject* JSObject::ReplaceSlowProperty(String* name, |
| 1462 Object* value, | 1463 Object* value, |
| 1463 PropertyAttributes attributes) { | 1464 PropertyAttributes attributes) { |
| 1464 StringDictionary* dictionary = property_dictionary(); | 1465 StringDictionary* dictionary = property_dictionary(); |
| (...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1569 set_properties(FixedArray::cast(new_properties)); | 1570 set_properties(FixedArray::cast(new_properties)); |
| 1570 } | 1571 } |
| 1571 return FastPropertyAtPut(index, new_value); | 1572 return FastPropertyAtPut(index, new_value); |
| 1572 } | 1573 } |
| 1573 | 1574 |
| 1574 | 1575 |
| 1575 | 1576 |
| 1576 MaybeObject* JSObject::SetPropertyWithInterceptor( | 1577 MaybeObject* JSObject::SetPropertyWithInterceptor( |
| 1577 String* name, | 1578 String* name, |
| 1578 Object* value, | 1579 Object* value, |
| 1579 PropertyAttributes attributes) { | 1580 PropertyAttributes attributes, |
| 1581 StrictModeFlag strict) { |
| 1580 HandleScope scope; | 1582 HandleScope scope; |
| 1581 Handle<JSObject> this_handle(this); | 1583 Handle<JSObject> this_handle(this); |
| 1582 Handle<String> name_handle(name); | 1584 Handle<String> name_handle(name); |
| 1583 Handle<Object> value_handle(value); | 1585 Handle<Object> value_handle(value); |
| 1584 Handle<InterceptorInfo> interceptor(GetNamedInterceptor()); | 1586 Handle<InterceptorInfo> interceptor(GetNamedInterceptor()); |
| 1585 if (!interceptor->setter()->IsUndefined()) { | 1587 if (!interceptor->setter()->IsUndefined()) { |
| 1586 LOG(ApiNamedPropertyAccess("interceptor-named-set", this, name)); | 1588 LOG(ApiNamedPropertyAccess("interceptor-named-set", this, name)); |
| 1587 CustomArguments args(interceptor->data(), this, this); | 1589 CustomArguments args(interceptor->data(), this, this); |
| 1588 v8::AccessorInfo info(args.end()); | 1590 v8::AccessorInfo info(args.end()); |
| 1589 v8::NamedPropertySetter setter = | 1591 v8::NamedPropertySetter setter = |
| 1590 v8::ToCData<v8::NamedPropertySetter>(interceptor->setter()); | 1592 v8::ToCData<v8::NamedPropertySetter>(interceptor->setter()); |
| 1591 v8::Handle<v8::Value> result; | 1593 v8::Handle<v8::Value> result; |
| 1592 { | 1594 { |
| 1593 // Leaving JavaScript. | 1595 // Leaving JavaScript. |
| 1594 VMState state(EXTERNAL); | 1596 VMState state(EXTERNAL); |
| 1595 Handle<Object> value_unhole(value->IsTheHole() ? | 1597 Handle<Object> value_unhole(value->IsTheHole() ? |
| 1596 Heap::undefined_value() : | 1598 Heap::undefined_value() : |
| 1597 value); | 1599 value); |
| 1598 result = setter(v8::Utils::ToLocal(name_handle), | 1600 result = setter(v8::Utils::ToLocal(name_handle), |
| 1599 v8::Utils::ToLocal(value_unhole), | 1601 v8::Utils::ToLocal(value_unhole), |
| 1600 info); | 1602 info); |
| 1601 } | 1603 } |
| 1602 RETURN_IF_SCHEDULED_EXCEPTION(); | 1604 RETURN_IF_SCHEDULED_EXCEPTION(); |
| 1603 if (!result.IsEmpty()) return *value_handle; | 1605 if (!result.IsEmpty()) return *value_handle; |
| 1604 } | 1606 } |
| 1605 MaybeObject* raw_result = | 1607 MaybeObject* raw_result = |
| 1606 this_handle->SetPropertyPostInterceptor(*name_handle, | 1608 this_handle->SetPropertyPostInterceptor(*name_handle, |
| 1607 *value_handle, | 1609 *value_handle, |
| 1608 attributes); | 1610 attributes, |
| 1611 strict); |
| 1609 RETURN_IF_SCHEDULED_EXCEPTION(); | 1612 RETURN_IF_SCHEDULED_EXCEPTION(); |
| 1610 return raw_result; | 1613 return raw_result; |
| 1611 } | 1614 } |
| 1612 | 1615 |
| 1613 | 1616 |
| 1614 MaybeObject* JSObject::SetProperty(String* name, | 1617 MaybeObject* JSObject::SetProperty(String* name, |
| 1615 Object* value, | 1618 Object* value, |
| 1616 PropertyAttributes attributes) { | 1619 PropertyAttributes attributes, |
| 1620 StrictModeFlag strict) { |
| 1617 LookupResult result; | 1621 LookupResult result; |
| 1618 LocalLookup(name, &result); | 1622 LocalLookup(name, &result); |
| 1619 return SetProperty(&result, name, value, attributes); | 1623 return SetProperty(&result, name, value, attributes, strict); |
| 1620 } | 1624 } |
| 1621 | 1625 |
| 1622 | 1626 |
| 1623 MaybeObject* JSObject::SetPropertyWithCallback(Object* structure, | 1627 MaybeObject* JSObject::SetPropertyWithCallback(Object* structure, |
| 1624 String* name, | 1628 String* name, |
| 1625 Object* value, | 1629 Object* value, |
| 1626 JSObject* holder) { | 1630 JSObject* holder) { |
| 1627 HandleScope scope; | 1631 HandleScope scope; |
| 1628 | 1632 |
| 1629 // We should never get here to initialize a const with the hole | 1633 // We should never get here to initialize a const with the hole |
| (...skipping 259 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1889 HandleScope scope; | 1893 HandleScope scope; |
| 1890 Handle<Object> value_handle(value); | 1894 Handle<Object> value_handle(value); |
| 1891 Top::ReportFailedAccessCheck(this, v8::ACCESS_SET); | 1895 Top::ReportFailedAccessCheck(this, v8::ACCESS_SET); |
| 1892 return *value_handle; | 1896 return *value_handle; |
| 1893 } | 1897 } |
| 1894 | 1898 |
| 1895 | 1899 |
| 1896 MaybeObject* JSObject::SetProperty(LookupResult* result, | 1900 MaybeObject* JSObject::SetProperty(LookupResult* result, |
| 1897 String* name, | 1901 String* name, |
| 1898 Object* value, | 1902 Object* value, |
| 1899 PropertyAttributes attributes) { | 1903 PropertyAttributes attributes, |
| 1904 StrictModeFlag strict) { |
| 1900 // Make sure that the top context does not change when doing callbacks or | 1905 // Make sure that the top context does not change when doing callbacks or |
| 1901 // interceptor calls. | 1906 // interceptor calls. |
| 1902 AssertNoContextChange ncc; | 1907 AssertNoContextChange ncc; |
| 1903 | 1908 |
| 1904 // Optimization for 2-byte strings often used as keys in a decompression | 1909 // Optimization for 2-byte strings often used as keys in a decompression |
| 1905 // dictionary. We make these short keys into symbols to avoid constantly | 1910 // dictionary. We make these short keys into symbols to avoid constantly |
| 1906 // reallocating them. | 1911 // reallocating them. |
| 1907 if (!name->IsSymbol() && name->length() <= 2) { | 1912 if (!name->IsSymbol() && name->length() <= 2) { |
| 1908 Object* symbol_version; | 1913 Object* symbol_version; |
| 1909 { MaybeObject* maybe_symbol_version = Heap::LookupSymbol(name); | 1914 { MaybeObject* maybe_symbol_version = Heap::LookupSymbol(name); |
| 1910 if (maybe_symbol_version->ToObject(&symbol_version)) { | 1915 if (maybe_symbol_version->ToObject(&symbol_version)) { |
| 1911 name = String::cast(symbol_version); | 1916 name = String::cast(symbol_version); |
| 1912 } | 1917 } |
| 1913 } | 1918 } |
| 1914 } | 1919 } |
| 1915 | 1920 |
| 1916 // Check access rights if needed. | 1921 // Check access rights if needed. |
| 1917 if (IsAccessCheckNeeded() | 1922 if (IsAccessCheckNeeded() |
| 1918 && !Top::MayNamedAccess(this, name, v8::ACCESS_SET)) { | 1923 && !Top::MayNamedAccess(this, name, v8::ACCESS_SET)) { |
| 1919 return SetPropertyWithFailedAccessCheck(result, name, value, true); | 1924 return SetPropertyWithFailedAccessCheck(result, name, value, true); |
| 1920 } | 1925 } |
| 1921 | 1926 |
| 1922 if (IsJSGlobalProxy()) { | 1927 if (IsJSGlobalProxy()) { |
| 1923 Object* proto = GetPrototype(); | 1928 Object* proto = GetPrototype(); |
| 1924 if (proto->IsNull()) return value; | 1929 if (proto->IsNull()) return value; |
| 1925 ASSERT(proto->IsJSGlobalObject()); | 1930 ASSERT(proto->IsJSGlobalObject()); |
| 1926 return JSObject::cast(proto)->SetProperty(result, name, value, attributes); | 1931 return JSObject::cast(proto)->SetProperty( |
| 1932 result, name, value, attributes, strict); |
| 1927 } | 1933 } |
| 1928 | 1934 |
| 1929 if (!result->IsProperty() && !IsJSContextExtensionObject()) { | 1935 if (!result->IsProperty() && !IsJSContextExtensionObject()) { |
| 1930 // We could not find a local property so let's check whether there is an | 1936 // We could not find a local property so let's check whether there is an |
| 1931 // accessor that wants to handle the property. | 1937 // accessor that wants to handle the property. |
| 1932 LookupResult accessor_result; | 1938 LookupResult accessor_result; |
| 1933 LookupCallbackSetterInPrototypes(name, &accessor_result); | 1939 LookupCallbackSetterInPrototypes(name, &accessor_result); |
| 1934 if (accessor_result.IsProperty()) { | 1940 if (accessor_result.IsProperty()) { |
| 1935 return SetPropertyWithCallback(accessor_result.GetCallbackObject(), | 1941 return SetPropertyWithCallback(accessor_result.GetCallbackObject(), |
| 1936 name, | 1942 name, |
| 1937 value, | 1943 value, |
| 1938 accessor_result.holder()); | 1944 accessor_result.holder()); |
| 1939 } | 1945 } |
| 1940 } | 1946 } |
| 1941 if (!result->IsFound()) { | 1947 if (!result->IsFound()) { |
| 1942 // Neither properties nor transitions found. | 1948 // Neither properties nor transitions found. |
| 1943 return AddProperty(name, value, attributes); | 1949 return AddProperty(name, value, attributes); |
| 1944 } | 1950 } |
| 1945 if (result->IsReadOnly() && result->IsProperty()) return value; | 1951 if (result->IsReadOnly() && result->IsProperty()) { |
| 1952 if (strict == kStrictMode) { |
| 1953 HandleScope scope; |
| 1954 Handle<String> key(name); |
| 1955 Handle<Object> holder(this); |
| 1956 Handle<Object> args[2] = { key, holder }; |
| 1957 return Top::Throw(*Factory::NewTypeError("strict_read_only_property", |
| 1958 HandleVector(args, 2))); |
| 1959 |
| 1960 } else { |
| 1961 return value; |
| 1962 } |
| 1963 } |
| 1946 // This is a real property that is not read-only, or it is a | 1964 // This is a real property that is not read-only, or it is a |
| 1947 // transition or null descriptor and there are no setters in the prototypes. | 1965 // transition or null descriptor and there are no setters in the prototypes. |
| 1948 switch (result->type()) { | 1966 switch (result->type()) { |
| 1949 case NORMAL: | 1967 case NORMAL: |
| 1950 return SetNormalizedProperty(result, value); | 1968 return SetNormalizedProperty(result, value); |
| 1951 case FIELD: | 1969 case FIELD: |
| 1952 return FastPropertyAtPut(result->GetFieldIndex(), value); | 1970 return FastPropertyAtPut(result->GetFieldIndex(), value); |
| 1953 case MAP_TRANSITION: | 1971 case MAP_TRANSITION: |
| 1954 if (attributes == result->GetAttributes()) { | 1972 if (attributes == result->GetAttributes()) { |
| 1955 // Only use map transition if the attributes match. | 1973 // Only use map transition if the attributes match. |
| 1956 return AddFastPropertyUsingMap(result->GetTransitionMap(), | 1974 return AddFastPropertyUsingMap(result->GetTransitionMap(), |
| 1957 name, | 1975 name, |
| 1958 value); | 1976 value); |
| 1959 } | 1977 } |
| 1960 return ConvertDescriptorToField(name, value, attributes); | 1978 return ConvertDescriptorToField(name, value, attributes); |
| 1961 case CONSTANT_FUNCTION: | 1979 case CONSTANT_FUNCTION: |
| 1962 // Only replace the function if necessary. | 1980 // Only replace the function if necessary. |
| 1963 if (value == result->GetConstantFunction()) return value; | 1981 if (value == result->GetConstantFunction()) return value; |
| 1964 // Preserve the attributes of this existing property. | 1982 // Preserve the attributes of this existing property. |
| 1965 attributes = result->GetAttributes(); | 1983 attributes = result->GetAttributes(); |
| 1966 return ConvertDescriptorToField(name, value, attributes); | 1984 return ConvertDescriptorToField(name, value, attributes); |
| 1967 case CALLBACKS: | 1985 case CALLBACKS: |
| 1968 return SetPropertyWithCallback(result->GetCallbackObject(), | 1986 return SetPropertyWithCallback(result->GetCallbackObject(), |
| 1969 name, | 1987 name, |
| 1970 value, | 1988 value, |
| 1971 result->holder()); | 1989 result->holder()); |
| 1972 case INTERCEPTOR: | 1990 case INTERCEPTOR: |
| 1973 return SetPropertyWithInterceptor(name, value, attributes); | 1991 return SetPropertyWithInterceptor(name, value, attributes, strict); |
| 1974 case CONSTANT_TRANSITION: { | 1992 case CONSTANT_TRANSITION: { |
| 1975 // If the same constant function is being added we can simply | 1993 // If the same constant function is being added we can simply |
| 1976 // transition to the target map. | 1994 // transition to the target map. |
| 1977 Map* target_map = result->GetTransitionMap(); | 1995 Map* target_map = result->GetTransitionMap(); |
| 1978 DescriptorArray* target_descriptors = target_map->instance_descriptors(); | 1996 DescriptorArray* target_descriptors = target_map->instance_descriptors(); |
| 1979 int number = target_descriptors->SearchWithCache(name); | 1997 int number = target_descriptors->SearchWithCache(name); |
| 1980 ASSERT(number != DescriptorArray::kNotFound); | 1998 ASSERT(number != DescriptorArray::kNotFound); |
| 1981 ASSERT(target_descriptors->GetType(number) == CONSTANT_FUNCTION); | 1999 ASSERT(target_descriptors->GetType(number) == CONSTANT_FUNCTION); |
| 1982 JSFunction* function = | 2000 JSFunction* function = |
| 1983 JSFunction::cast(target_descriptors->GetValue(number)); | 2001 JSFunction::cast(target_descriptors->GetValue(number)); |
| (...skipping 4296 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6280 | 6298 |
| 6281 void Code::PrintExtraICState(FILE* out, Kind kind, ExtraICState extra) { | 6299 void Code::PrintExtraICState(FILE* out, Kind kind, ExtraICState extra) { |
| 6282 const char* name = NULL; | 6300 const char* name = NULL; |
| 6283 switch (kind) { | 6301 switch (kind) { |
| 6284 case CALL_IC: | 6302 case CALL_IC: |
| 6285 if (extra == STRING_INDEX_OUT_OF_BOUNDS) { | 6303 if (extra == STRING_INDEX_OUT_OF_BOUNDS) { |
| 6286 name = "STRING_INDEX_OUT_OF_BOUNDS"; | 6304 name = "STRING_INDEX_OUT_OF_BOUNDS"; |
| 6287 } | 6305 } |
| 6288 break; | 6306 break; |
| 6289 case STORE_IC: | 6307 case STORE_IC: |
| 6290 if (extra == StoreIC::kStoreICStrict) { | 6308 case KEYED_STORE_IC: |
| 6309 if (extra == kStrictMode) { |
| 6291 name = "STRICT"; | 6310 name = "STRICT"; |
| 6292 } | 6311 } |
| 6293 break; | 6312 break; |
| 6294 default: | 6313 default: |
| 6295 break; | 6314 break; |
| 6296 } | 6315 } |
| 6297 if (name != NULL) { | 6316 if (name != NULL) { |
| 6298 PrintF(out, "extra_ic_state = %s\n", name); | 6317 PrintF(out, "extra_ic_state = %s\n", name); |
| 6299 } else { | 6318 } else { |
| 6300 PrintF(out, "etra_ic_state = %d\n", extra); | 6319 PrintF(out, "etra_ic_state = %d\n", extra); |
| (...skipping 3715 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10016 if (break_point_objects()->IsUndefined()) return 0; | 10035 if (break_point_objects()->IsUndefined()) return 0; |
| 10017 // Single beak point. | 10036 // Single beak point. |
| 10018 if (!break_point_objects()->IsFixedArray()) return 1; | 10037 if (!break_point_objects()->IsFixedArray()) return 1; |
| 10019 // Multiple break points. | 10038 // Multiple break points. |
| 10020 return FixedArray::cast(break_point_objects())->length(); | 10039 return FixedArray::cast(break_point_objects())->length(); |
| 10021 } | 10040 } |
| 10022 #endif | 10041 #endif |
| 10023 | 10042 |
| 10024 | 10043 |
| 10025 } } // namespace v8::internal | 10044 } } // namespace v8::internal |
| OLD | NEW |