| 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 1845 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1856 JSObject::cast(pt)->LocalLookupRealNamedProperty(name, result); | 1856 JSObject::cast(pt)->LocalLookupRealNamedProperty(name, result); |
| 1857 if (result->IsProperty() && (result->type() != INTERCEPTOR)) return; | 1857 if (result->IsProperty() && (result->type() != INTERCEPTOR)) return; |
| 1858 } | 1858 } |
| 1859 result->NotFound(); | 1859 result->NotFound(); |
| 1860 } | 1860 } |
| 1861 | 1861 |
| 1862 | 1862 |
| 1863 // We only need to deal with CALLBACKS and INTERCEPTORS | 1863 // We only need to deal with CALLBACKS and INTERCEPTORS |
| 1864 MaybeObject* JSObject::SetPropertyWithFailedAccessCheck(LookupResult* result, | 1864 MaybeObject* JSObject::SetPropertyWithFailedAccessCheck(LookupResult* result, |
| 1865 String* name, | 1865 String* name, |
| 1866 Object* value) { | 1866 Object* value, |
| 1867 bool check_prototype) { |
| 1867 Heap* heap = GetHeap(); | 1868 Heap* heap = GetHeap(); |
| 1868 if (!result->IsProperty()) { | 1869 if (check_prototype && !result->IsProperty()) { |
| 1869 LookupCallbackSetterInPrototypes(name, result); | 1870 LookupCallbackSetterInPrototypes(name, result); |
| 1870 } | 1871 } |
| 1871 | 1872 |
| 1872 if (result->IsProperty()) { | 1873 if (result->IsProperty()) { |
| 1873 if (!result->IsReadOnly()) { | 1874 if (!result->IsReadOnly()) { |
| 1874 switch (result->type()) { | 1875 switch (result->type()) { |
| 1875 case CALLBACKS: { | 1876 case CALLBACKS: { |
| 1876 Object* obj = result->GetCallbackObject(); | 1877 Object* obj = result->GetCallbackObject(); |
| 1877 if (obj->IsAccessorInfo()) { | 1878 if (obj->IsAccessorInfo()) { |
| 1878 AccessorInfo* info = AccessorInfo::cast(obj); | 1879 AccessorInfo* info = AccessorInfo::cast(obj); |
| 1879 if (info->all_can_write()) { | 1880 if (info->all_can_write()) { |
| 1880 return SetPropertyWithCallback(result->GetCallbackObject(), | 1881 return SetPropertyWithCallback(result->GetCallbackObject(), |
| 1881 name, | 1882 name, |
| 1882 value, | 1883 value, |
| 1883 result->holder()); | 1884 result->holder()); |
| 1884 } | 1885 } |
| 1885 } | 1886 } |
| 1886 break; | 1887 break; |
| 1887 } | 1888 } |
| 1888 case INTERCEPTOR: { | 1889 case INTERCEPTOR: { |
| 1889 // Try lookup real named properties. Note that only property can be | 1890 // Try lookup real named properties. Note that only property can be |
| 1890 // set is callbacks marked as ALL_CAN_WRITE on the prototype chain. | 1891 // set is callbacks marked as ALL_CAN_WRITE on the prototype chain. |
| 1891 LookupResult r; | 1892 LookupResult r; |
| 1892 LookupRealNamedProperty(name, &r); | 1893 LookupRealNamedProperty(name, &r); |
| 1893 if (r.IsProperty()) { | 1894 if (r.IsProperty()) { |
| 1894 return SetPropertyWithFailedAccessCheck(&r, name, value); | 1895 return SetPropertyWithFailedAccessCheck(&r, name, value, |
| 1896 check_prototype); |
| 1895 } | 1897 } |
| 1896 break; | 1898 break; |
| 1897 } | 1899 } |
| 1898 default: { | 1900 default: { |
| 1899 break; | 1901 break; |
| 1900 } | 1902 } |
| 1901 } | 1903 } |
| 1902 } | 1904 } |
| 1903 } | 1905 } |
| 1904 | 1906 |
| (...skipping 21 matching lines...) Expand all Loading... |
| 1926 { MaybeObject* maybe_symbol_version = heap->LookupSymbol(name); | 1928 { MaybeObject* maybe_symbol_version = heap->LookupSymbol(name); |
| 1927 if (maybe_symbol_version->ToObject(&symbol_version)) { | 1929 if (maybe_symbol_version->ToObject(&symbol_version)) { |
| 1928 name = String::cast(symbol_version); | 1930 name = String::cast(symbol_version); |
| 1929 } | 1931 } |
| 1930 } | 1932 } |
| 1931 } | 1933 } |
| 1932 | 1934 |
| 1933 // Check access rights if needed. | 1935 // Check access rights if needed. |
| 1934 if (IsAccessCheckNeeded() | 1936 if (IsAccessCheckNeeded() |
| 1935 && !heap->isolate()->MayNamedAccess(this, name, v8::ACCESS_SET)) { | 1937 && !heap->isolate()->MayNamedAccess(this, name, v8::ACCESS_SET)) { |
| 1936 return SetPropertyWithFailedAccessCheck(result, name, value); | 1938 return SetPropertyWithFailedAccessCheck(result, name, value, true); |
| 1937 } | 1939 } |
| 1938 | 1940 |
| 1939 if (IsJSGlobalProxy()) { | 1941 if (IsJSGlobalProxy()) { |
| 1940 Object* proto = GetPrototype(); | 1942 Object* proto = GetPrototype(); |
| 1941 if (proto->IsNull()) return value; | 1943 if (proto->IsNull()) return value; |
| 1942 ASSERT(proto->IsJSGlobalObject()); | 1944 ASSERT(proto->IsJSGlobalObject()); |
| 1943 return JSObject::cast(proto)->SetProperty(result, name, value, attributes); | 1945 return JSObject::cast(proto)->SetProperty(result, name, value, attributes); |
| 1944 } | 1946 } |
| 1945 | 1947 |
| 1946 if (!result->IsProperty() && !IsJSContextExtensionObject()) { | 1948 if (!result->IsProperty() && !IsJSContextExtensionObject()) { |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2016 return value; | 2018 return value; |
| 2017 } | 2019 } |
| 2018 | 2020 |
| 2019 | 2021 |
| 2020 // Set a real local property, even if it is READ_ONLY. If the property is not | 2022 // Set a real local property, even if it is READ_ONLY. If the property is not |
| 2021 // present, add it with attributes NONE. This code is an exact clone of | 2023 // present, add it with attributes NONE. This code is an exact clone of |
| 2022 // SetProperty, with the check for IsReadOnly and the check for a | 2024 // SetProperty, with the check for IsReadOnly and the check for a |
| 2023 // callback setter removed. The two lines looking up the LookupResult | 2025 // callback setter removed. The two lines looking up the LookupResult |
| 2024 // result are also added. If one of the functions is changed, the other | 2026 // result are also added. If one of the functions is changed, the other |
| 2025 // should be. | 2027 // should be. |
| 2026 MaybeObject* JSObject::IgnoreAttributesAndSetLocalProperty( | 2028 MaybeObject* JSObject::SetLocalPropertyIgnoreAttributes( |
| 2027 String* name, | 2029 String* name, |
| 2028 Object* value, | 2030 Object* value, |
| 2029 PropertyAttributes attributes) { | 2031 PropertyAttributes attributes) { |
| 2030 Heap* heap = GetHeap(); | 2032 Heap* heap = GetHeap(); |
| 2031 | 2033 |
| 2032 // Make sure that the top context does not change when doing callbacks or | 2034 // Make sure that the top context does not change when doing callbacks or |
| 2033 // interceptor calls. | 2035 // interceptor calls. |
| 2034 AssertNoContextChange ncc; | 2036 AssertNoContextChange ncc; |
| 2035 LookupResult result; | 2037 LookupResult result; |
| 2036 LocalLookup(name, &result); | 2038 LocalLookup(name, &result); |
| 2037 // Check access rights if needed. | 2039 // Check access rights if needed. |
| 2038 if (IsAccessCheckNeeded() | 2040 if (IsAccessCheckNeeded() |
| 2039 && !heap->isolate()->MayNamedAccess(this, name, v8::ACCESS_SET)) { | 2041 && !heap->isolate()->MayNamedAccess(this, name, v8::ACCESS_SET)) { |
| 2040 return SetPropertyWithFailedAccessCheck(&result, name, value); | 2042 return SetPropertyWithFailedAccessCheck(&result, name, value, false); |
| 2041 } | 2043 } |
| 2042 | 2044 |
| 2043 if (IsJSGlobalProxy()) { | 2045 if (IsJSGlobalProxy()) { |
| 2044 Object* proto = GetPrototype(); | 2046 Object* proto = GetPrototype(); |
| 2045 if (proto->IsNull()) return value; | 2047 if (proto->IsNull()) return value; |
| 2046 ASSERT(proto->IsJSGlobalObject()); | 2048 ASSERT(proto->IsJSGlobalObject()); |
| 2047 return JSObject::cast(proto)->IgnoreAttributesAndSetLocalProperty( | 2049 return JSObject::cast(proto)->SetLocalPropertyIgnoreAttributes( |
| 2048 name, | 2050 name, |
| 2049 value, | 2051 value, |
| 2050 attributes); | 2052 attributes); |
| 2051 } | 2053 } |
| 2052 | 2054 |
| 2053 // Check for accessor in prototype chain removed here in clone. | 2055 // Check for accessor in prototype chain removed here in clone. |
| 2054 if (!result.IsFound()) { | 2056 if (!result.IsFound()) { |
| 2055 // Neither properties nor transitions found. | 2057 // Neither properties nor transitions found. |
| 2056 return AddProperty(name, value, attributes); | 2058 return AddProperty(name, value, attributes); |
| 2057 } | 2059 } |
| (...skipping 934 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2992 | 2994 |
| 2993 // Try to flatten before operating on the string. | 2995 // Try to flatten before operating on the string. |
| 2994 name->TryFlatten(); | 2996 name->TryFlatten(); |
| 2995 | 2997 |
| 2996 if (!CanSetCallback(name)) { | 2998 if (!CanSetCallback(name)) { |
| 2997 return heap->undefined_value(); | 2999 return heap->undefined_value(); |
| 2998 } | 3000 } |
| 2999 | 3001 |
| 3000 uint32_t index = 0; | 3002 uint32_t index = 0; |
| 3001 bool is_element = name->AsArrayIndex(&index); | 3003 bool is_element = name->AsArrayIndex(&index); |
| 3002 if (is_element && IsJSArray()) return heap->undefined_value(); | |
| 3003 | 3004 |
| 3004 if (is_element) { | 3005 if (is_element) { |
| 3005 switch (GetElementsKind()) { | 3006 switch (GetElementsKind()) { |
| 3006 case FAST_ELEMENTS: | 3007 case FAST_ELEMENTS: |
| 3007 break; | 3008 break; |
| 3008 case PIXEL_ELEMENTS: | 3009 case PIXEL_ELEMENTS: |
| 3009 case EXTERNAL_BYTE_ELEMENTS: | 3010 case EXTERNAL_BYTE_ELEMENTS: |
| 3010 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: | 3011 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: |
| 3011 case EXTERNAL_SHORT_ELEMENTS: | 3012 case EXTERNAL_SHORT_ELEMENTS: |
| 3012 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: | 3013 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: |
| (...skipping 2214 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5227 decoder->Reset(str.start(), str.length()); | 5228 decoder->Reset(str.start(), str.length()); |
| 5228 int i; | 5229 int i; |
| 5229 for (i = 0; i < slen && decoder->has_more(); i++) { | 5230 for (i = 0; i < slen && decoder->has_more(); i++) { |
| 5230 uc32 r = decoder->GetNext(); | 5231 uc32 r = decoder->GetNext(); |
| 5231 if (Get(i) != r) return false; | 5232 if (Get(i) != r) return false; |
| 5232 } | 5233 } |
| 5233 return i == slen && !decoder->has_more(); | 5234 return i == slen && !decoder->has_more(); |
| 5234 } | 5235 } |
| 5235 | 5236 |
| 5236 | 5237 |
| 5238 bool String::IsAsciiEqualTo(Vector<const char> str) { |
| 5239 int slen = length(); |
| 5240 if (str.length() != slen) return false; |
| 5241 for (int i = 0; i < slen; i++) { |
| 5242 if (Get(i) != static_cast<uint16_t>(str[i])) return false; |
| 5243 } |
| 5244 return true; |
| 5245 } |
| 5246 |
| 5247 |
| 5248 bool String::IsTwoByteEqualTo(Vector<const uc16> str) { |
| 5249 int slen = length(); |
| 5250 if (str.length() != slen) return false; |
| 5251 for (int i = 0; i < slen; i++) { |
| 5252 if (Get(i) != str[i]) return false; |
| 5253 } |
| 5254 return true; |
| 5255 } |
| 5256 |
| 5257 |
| 5237 template <typename schar> | 5258 template <typename schar> |
| 5238 static inline uint32_t HashSequentialString(const schar* chars, int length) { | 5259 static inline uint32_t HashSequentialString(const schar* chars, int length) { |
| 5239 StringHasher hasher(length); | 5260 StringHasher hasher(length); |
| 5240 if (!hasher.has_trivial_hash()) { | 5261 if (!hasher.has_trivial_hash()) { |
| 5241 int i; | 5262 int i; |
| 5242 for (i = 0; hasher.is_array_index() && (i < length); i++) { | 5263 for (i = 0; hasher.is_array_index() && (i < length); i++) { |
| 5243 hasher.AddCharacter(chars[i]); | 5264 hasher.AddCharacter(chars[i]); |
| 5244 } | 5265 } |
| 5245 for (; i < length; i++) { | 5266 for (; i < length; i++) { |
| 5246 hasher.AddCharacterNoIndex(chars[i]); | 5267 hasher.AddCharacterNoIndex(chars[i]); |
| (...skipping 820 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6067 if (statement_position < p && p <= position) { | 6088 if (statement_position < p && p <= position) { |
| 6068 statement_position = p; | 6089 statement_position = p; |
| 6069 } | 6090 } |
| 6070 } | 6091 } |
| 6071 it.next(); | 6092 it.next(); |
| 6072 } | 6093 } |
| 6073 return statement_position; | 6094 return statement_position; |
| 6074 } | 6095 } |
| 6075 | 6096 |
| 6076 | 6097 |
| 6077 uint8_t* Code::GetSafepointEntry(Address pc) { | 6098 SafepointEntry Code::GetSafepointEntry(Address pc) { |
| 6078 SafepointTable table(this); | 6099 SafepointTable table(this); |
| 6079 unsigned pc_offset = static_cast<unsigned>(pc - instruction_start()); | 6100 return table.FindEntry(pc); |
| 6080 for (unsigned i = 0; i < table.length(); i++) { | |
| 6081 // TODO(kasperl): Replace the linear search with binary search. | |
| 6082 if (table.GetPcOffset(i) == pc_offset) return table.GetEntry(i); | |
| 6083 } | |
| 6084 return NULL; | |
| 6085 } | 6101 } |
| 6086 | 6102 |
| 6087 | 6103 |
| 6088 void Code::SetNoStackCheckTable() { | 6104 void Code::SetNoStackCheckTable() { |
| 6089 // Indicate the absence of a stack-check table by a table start after the | 6105 // Indicate the absence of a stack-check table by a table start after the |
| 6090 // end of the instructions. Table start must be aligned, so round up. | 6106 // end of the instructions. Table start must be aligned, so round up. |
| 6091 set_stack_check_table_start(RoundUp(instruction_size(), kIntSize)); | 6107 set_stack_check_table_start(RoundUp(instruction_size(), kIntSize)); |
| 6092 } | 6108 } |
| 6093 | 6109 |
| 6094 | 6110 |
| (...skipping 250 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6345 #endif | 6361 #endif |
| 6346 | 6362 |
| 6347 if (kind() == OPTIMIZED_FUNCTION) { | 6363 if (kind() == OPTIMIZED_FUNCTION) { |
| 6348 SafepointTable table(this); | 6364 SafepointTable table(this); |
| 6349 PrintF(out, "Safepoints (size = %u)\n", table.size()); | 6365 PrintF(out, "Safepoints (size = %u)\n", table.size()); |
| 6350 for (unsigned i = 0; i < table.length(); i++) { | 6366 for (unsigned i = 0; i < table.length(); i++) { |
| 6351 unsigned pc_offset = table.GetPcOffset(i); | 6367 unsigned pc_offset = table.GetPcOffset(i); |
| 6352 PrintF(out, "%p %4d ", (instruction_start() + pc_offset), pc_offset); | 6368 PrintF(out, "%p %4d ", (instruction_start() + pc_offset), pc_offset); |
| 6353 table.PrintEntry(i); | 6369 table.PrintEntry(i); |
| 6354 PrintF(out, " (sp -> fp)"); | 6370 PrintF(out, " (sp -> fp)"); |
| 6355 int deoptimization_index = table.GetDeoptimizationIndex(i); | 6371 SafepointEntry entry = table.GetEntry(i); |
| 6356 if (deoptimization_index != Safepoint::kNoDeoptimizationIndex) { | 6372 if (entry.deoptimization_index() != Safepoint::kNoDeoptimizationIndex) { |
| 6357 PrintF(out, " %6d", deoptimization_index); | 6373 PrintF(out, " %6d", entry.deoptimization_index()); |
| 6358 } else { | 6374 } else { |
| 6359 PrintF(out, " <none>"); | 6375 PrintF(out, " <none>"); |
| 6360 } | 6376 } |
| 6377 if (entry.argument_count() > 0) { |
| 6378 PrintF(out, " argc: %d", entry.argument_count()); |
| 6379 } |
| 6361 PrintF(out, "\n"); | 6380 PrintF(out, "\n"); |
| 6362 } | 6381 } |
| 6363 PrintF(out, "\n"); | 6382 PrintF(out, "\n"); |
| 6364 } else if (kind() == FUNCTION) { | 6383 } else if (kind() == FUNCTION) { |
| 6365 unsigned offset = stack_check_table_start(); | 6384 unsigned offset = stack_check_table_start(); |
| 6366 // If there is no stack check table, the "table start" will at or after | 6385 // If there is no stack check table, the "table start" will at or after |
| 6367 // (due to alignment) the end of the instruction stream. | 6386 // (due to alignment) the end of the instruction stream. |
| 6368 if (static_cast<int>(offset) < instruction_size()) { | 6387 if (static_cast<int>(offset) < instruction_size()) { |
| 6369 unsigned* address = | 6388 unsigned* address = |
| 6370 reinterpret_cast<unsigned*>(instruction_start() + offset); | 6389 reinterpret_cast<unsigned*>(instruction_start() + offset); |
| (...skipping 515 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6886 // Handle [] on String objects. | 6905 // Handle [] on String objects. |
| 6887 if (this->IsStringObjectWithCharacterAt(index)) return true; | 6906 if (this->IsStringObjectWithCharacterAt(index)) return true; |
| 6888 | 6907 |
| 6889 Object* pt = GetPrototype(); | 6908 Object* pt = GetPrototype(); |
| 6890 if (pt->IsNull()) return false; | 6909 if (pt->IsNull()) return false; |
| 6891 return JSObject::cast(pt)->HasElementWithReceiver(receiver, index); | 6910 return JSObject::cast(pt)->HasElementWithReceiver(receiver, index); |
| 6892 } | 6911 } |
| 6893 | 6912 |
| 6894 | 6913 |
| 6895 MaybeObject* JSObject::SetElementWithInterceptor(uint32_t index, | 6914 MaybeObject* JSObject::SetElementWithInterceptor(uint32_t index, |
| 6896 Object* value) { | 6915 Object* value, |
| 6916 bool check_prototype) { |
| 6897 Isolate* isolate = GetIsolate(); | 6917 Isolate* isolate = GetIsolate(); |
| 6898 // Make sure that the top context does not change when doing | 6918 // Make sure that the top context does not change when doing |
| 6899 // callbacks or interceptor calls. | 6919 // callbacks or interceptor calls. |
| 6900 AssertNoContextChange ncc; | 6920 AssertNoContextChange ncc; |
| 6901 HandleScope scope(isolate); | 6921 HandleScope scope(isolate); |
| 6902 Handle<InterceptorInfo> interceptor(GetIndexedInterceptor()); | 6922 Handle<InterceptorInfo> interceptor(GetIndexedInterceptor()); |
| 6903 Handle<JSObject> this_handle(this); | 6923 Handle<JSObject> this_handle(this); |
| 6904 Handle<Object> value_handle(value, isolate); | 6924 Handle<Object> value_handle(value, isolate); |
| 6905 if (!interceptor->setter()->IsUndefined()) { | 6925 if (!interceptor->setter()->IsUndefined()) { |
| 6906 v8::IndexedPropertySetter setter = | 6926 v8::IndexedPropertySetter setter = |
| 6907 v8::ToCData<v8::IndexedPropertySetter>(interceptor->setter()); | 6927 v8::ToCData<v8::IndexedPropertySetter>(interceptor->setter()); |
| 6908 LOG(ApiIndexedPropertyAccess("interceptor-indexed-set", this, index)); | 6928 LOG(ApiIndexedPropertyAccess("interceptor-indexed-set", this, index)); |
| 6909 CustomArguments args(isolate, interceptor->data(), this, this); | 6929 CustomArguments args(isolate, interceptor->data(), this, this); |
| 6910 v8::AccessorInfo info(args.end()); | 6930 v8::AccessorInfo info(args.end()); |
| 6911 v8::Handle<v8::Value> result; | 6931 v8::Handle<v8::Value> result; |
| 6912 { | 6932 { |
| 6913 // Leaving JavaScript. | 6933 // Leaving JavaScript. |
| 6914 VMState state(isolate, EXTERNAL); | 6934 VMState state(isolate, EXTERNAL); |
| 6915 result = setter(index, v8::Utils::ToLocal(value_handle), info); | 6935 result = setter(index, v8::Utils::ToLocal(value_handle), info); |
| 6916 } | 6936 } |
| 6917 RETURN_IF_SCHEDULED_EXCEPTION(isolate); | 6937 RETURN_IF_SCHEDULED_EXCEPTION(isolate); |
| 6918 if (!result.IsEmpty()) return *value_handle; | 6938 if (!result.IsEmpty()) return *value_handle; |
| 6919 } | 6939 } |
| 6920 MaybeObject* raw_result = | 6940 MaybeObject* raw_result = |
| 6921 this_handle->SetElementWithoutInterceptor(index, *value_handle); | 6941 this_handle->SetElementWithoutInterceptor(index, |
| 6942 *value_handle, |
| 6943 check_prototype); |
| 6922 RETURN_IF_SCHEDULED_EXCEPTION(isolate); | 6944 RETURN_IF_SCHEDULED_EXCEPTION(isolate); |
| 6923 return raw_result; | 6945 return raw_result; |
| 6924 } | 6946 } |
| 6925 | 6947 |
| 6926 | 6948 |
| 6927 MaybeObject* JSObject::GetElementWithCallback(Object* receiver, | 6949 MaybeObject* JSObject::GetElementWithCallback(Object* receiver, |
| 6928 Object* structure, | 6950 Object* structure, |
| 6929 uint32_t index, | 6951 uint32_t index, |
| 6930 Object* holder) { | 6952 Object* holder) { |
| 6931 Isolate* isolate = GetIsolate(); | 6953 Isolate* isolate = GetIsolate(); |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7025 } | 7047 } |
| 7026 | 7048 |
| 7027 UNREACHABLE(); | 7049 UNREACHABLE(); |
| 7028 return NULL; | 7050 return NULL; |
| 7029 } | 7051 } |
| 7030 | 7052 |
| 7031 | 7053 |
| 7032 // Adding n elements in fast case is O(n*n). | 7054 // Adding n elements in fast case is O(n*n). |
| 7033 // Note: revisit design to have dual undefined values to capture absent | 7055 // Note: revisit design to have dual undefined values to capture absent |
| 7034 // elements. | 7056 // elements. |
| 7035 MaybeObject* JSObject::SetFastElement(uint32_t index, Object* value) { | 7057 MaybeObject* JSObject::SetFastElement(uint32_t index, |
| 7058 Object* value, |
| 7059 bool check_prototype) { |
| 7036 ASSERT(HasFastElements()); | 7060 ASSERT(HasFastElements()); |
| 7037 | 7061 |
| 7038 Object* elms_obj; | 7062 Object* elms_obj; |
| 7039 { MaybeObject* maybe_elms_obj = EnsureWritableFastElements(); | 7063 { MaybeObject* maybe_elms_obj = EnsureWritableFastElements(); |
| 7040 if (!maybe_elms_obj->ToObject(&elms_obj)) return maybe_elms_obj; | 7064 if (!maybe_elms_obj->ToObject(&elms_obj)) return maybe_elms_obj; |
| 7041 } | 7065 } |
| 7042 FixedArray* elms = FixedArray::cast(elms_obj); | 7066 FixedArray* elms = FixedArray::cast(elms_obj); |
| 7043 uint32_t elms_length = static_cast<uint32_t>(elms->length()); | 7067 uint32_t elms_length = static_cast<uint32_t>(elms->length()); |
| 7044 | 7068 |
| 7045 if (!IsJSArray() && (index >= elms_length || elms->get(index)->IsTheHole())) { | 7069 if (check_prototype && |
| 7046 if (SetElementWithCallbackSetterInPrototypes(index, value)) { | 7070 (index >= elms_length || elms->get(index)->IsTheHole()) && |
| 7047 return value; | 7071 SetElementWithCallbackSetterInPrototypes(index, value)) { |
| 7048 } | 7072 return value; |
| 7049 } | 7073 } |
| 7050 | 7074 |
| 7075 |
| 7051 // Check whether there is extra space in fixed array.. | 7076 // Check whether there is extra space in fixed array.. |
| 7052 if (index < elms_length) { | 7077 if (index < elms_length) { |
| 7053 elms->set(index, value); | 7078 elms->set(index, value); |
| 7054 if (IsJSArray()) { | 7079 if (IsJSArray()) { |
| 7055 // Update the length of the array if needed. | 7080 // Update the length of the array if needed. |
| 7056 uint32_t array_length = 0; | 7081 uint32_t array_length = 0; |
| 7057 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&array_length)); | 7082 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&array_length)); |
| 7058 if (index >= array_length) { | 7083 if (index >= array_length) { |
| 7059 JSArray::cast(this)->set_length(Smi::FromInt(index + 1)); | 7084 JSArray::cast(this)->set_length(Smi::FromInt(index + 1)); |
| 7060 } | 7085 } |
| (...skipping 17 matching lines...) Expand all Loading... |
| 7078 return value; | 7103 return value; |
| 7079 } | 7104 } |
| 7080 } | 7105 } |
| 7081 | 7106 |
| 7082 // Otherwise default to slow case. | 7107 // Otherwise default to slow case. |
| 7083 Object* obj; | 7108 Object* obj; |
| 7084 { MaybeObject* maybe_obj = NormalizeElements(); | 7109 { MaybeObject* maybe_obj = NormalizeElements(); |
| 7085 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 7110 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 7086 } | 7111 } |
| 7087 ASSERT(HasDictionaryElements()); | 7112 ASSERT(HasDictionaryElements()); |
| 7088 return SetElement(index, value); | 7113 return SetElement(index, value, check_prototype); |
| 7089 } | 7114 } |
| 7090 | 7115 |
| 7091 | 7116 |
| 7092 MaybeObject* JSObject::SetElement(uint32_t index, Object* value) { | 7117 MaybeObject* JSObject::SetElement(uint32_t index, |
| 7118 Object* value, |
| 7119 bool check_prototype) { |
| 7093 Heap* heap = GetHeap(); | 7120 Heap* heap = GetHeap(); |
| 7094 // Check access rights if needed. | 7121 // Check access rights if needed. |
| 7095 if (IsAccessCheckNeeded() && | 7122 if (IsAccessCheckNeeded() && |
| 7096 !heap->isolate()->MayIndexedAccess(this, index, v8::ACCESS_SET)) { | 7123 !heap->isolate()->MayIndexedAccess(this, index, v8::ACCESS_SET)) { |
| 7097 HandleScope scope; | 7124 HandleScope scope; |
| 7098 Handle<Object> value_handle(value); | 7125 Handle<Object> value_handle(value); |
| 7099 heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_SET); | 7126 heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_SET); |
| 7100 return *value_handle; | 7127 return *value_handle; |
| 7101 } | 7128 } |
| 7102 | 7129 |
| 7103 if (IsJSGlobalProxy()) { | 7130 if (IsJSGlobalProxy()) { |
| 7104 Object* proto = GetPrototype(); | 7131 Object* proto = GetPrototype(); |
| 7105 if (proto->IsNull()) return value; | 7132 if (proto->IsNull()) return value; |
| 7106 ASSERT(proto->IsJSGlobalObject()); | 7133 ASSERT(proto->IsJSGlobalObject()); |
| 7107 return JSObject::cast(proto)->SetElement(index, value); | 7134 return JSObject::cast(proto)->SetElement(index, value, check_prototype); |
| 7108 } | 7135 } |
| 7109 | 7136 |
| 7110 // Check for lookup interceptor | 7137 // Check for lookup interceptor |
| 7111 if (HasIndexedInterceptor()) { | 7138 if (HasIndexedInterceptor()) { |
| 7112 return SetElementWithInterceptor(index, value); | 7139 return SetElementWithInterceptor(index, value, check_prototype); |
| 7113 } | 7140 } |
| 7114 | 7141 |
| 7115 return SetElementWithoutInterceptor(index, value); | 7142 return SetElementWithoutInterceptor(index, value, check_prototype); |
| 7116 } | 7143 } |
| 7117 | 7144 |
| 7118 | 7145 |
| 7119 MaybeObject* JSObject::SetElementWithoutInterceptor(uint32_t index, | 7146 MaybeObject* JSObject::SetElementWithoutInterceptor(uint32_t index, |
| 7120 Object* value) { | 7147 Object* value, |
| 7148 bool check_prototype) { |
| 7121 Heap* heap = GetHeap(); | 7149 Heap* heap = GetHeap(); |
| 7122 switch (GetElementsKind()) { | 7150 switch (GetElementsKind()) { |
| 7123 case FAST_ELEMENTS: | 7151 case FAST_ELEMENTS: |
| 7124 // Fast case. | 7152 // Fast case. |
| 7125 return SetFastElement(index, value); | 7153 return SetFastElement(index, value, check_prototype); |
| 7126 case PIXEL_ELEMENTS: { | 7154 case PIXEL_ELEMENTS: { |
| 7127 PixelArray* pixels = PixelArray::cast(elements()); | 7155 PixelArray* pixels = PixelArray::cast(elements()); |
| 7128 return pixels->SetValue(index, value); | 7156 return pixels->SetValue(index, value); |
| 7129 } | 7157 } |
| 7130 case EXTERNAL_BYTE_ELEMENTS: { | 7158 case EXTERNAL_BYTE_ELEMENTS: { |
| 7131 ExternalByteArray* array = ExternalByteArray::cast(elements()); | 7159 ExternalByteArray* array = ExternalByteArray::cast(elements()); |
| 7132 return array->SetValue(index, value); | 7160 return array->SetValue(index, value); |
| 7133 } | 7161 } |
| 7134 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: { | 7162 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: { |
| 7135 ExternalUnsignedByteArray* array = | 7163 ExternalUnsignedByteArray* array = |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7168 Object* element = dictionary->ValueAt(entry); | 7196 Object* element = dictionary->ValueAt(entry); |
| 7169 PropertyDetails details = dictionary->DetailsAt(entry); | 7197 PropertyDetails details = dictionary->DetailsAt(entry); |
| 7170 if (details.type() == CALLBACKS) { | 7198 if (details.type() == CALLBACKS) { |
| 7171 return SetElementWithCallback(element, index, value, this); | 7199 return SetElementWithCallback(element, index, value, this); |
| 7172 } else { | 7200 } else { |
| 7173 dictionary->UpdateMaxNumberKey(index); | 7201 dictionary->UpdateMaxNumberKey(index); |
| 7174 dictionary->ValueAtPut(entry, value); | 7202 dictionary->ValueAtPut(entry, value); |
| 7175 } | 7203 } |
| 7176 } else { | 7204 } else { |
| 7177 // Index not already used. Look for an accessor in the prototype chain. | 7205 // Index not already used. Look for an accessor in the prototype chain. |
| 7178 if (!IsJSArray()) { | 7206 if (check_prototype && |
| 7179 if (SetElementWithCallbackSetterInPrototypes(index, value)) { | 7207 SetElementWithCallbackSetterInPrototypes(index, value)) { |
| 7180 return value; | 7208 return value; |
| 7181 } | |
| 7182 } | 7209 } |
| 7183 // When we set the is_extensible flag to false we always force | 7210 // When we set the is_extensible flag to false we always force |
| 7184 // the element into dictionary mode (and force them to stay there). | 7211 // the element into dictionary mode (and force them to stay there). |
| 7185 if (!map()->is_extensible()) { | 7212 if (!map()->is_extensible()) { |
| 7186 Handle<Object> number(FACTORY->NewNumberFromUint(index)); | 7213 Handle<Object> number(FACTORY->NewNumberFromUint(index)); |
| 7187 Handle<String> index_string(FACTORY->NumberToString(number)); | 7214 Handle<String> index_string(FACTORY->NumberToString(number)); |
| 7188 Handle<Object> args[1] = { index_string }; | 7215 Handle<Object> args[1] = { index_string }; |
| 7189 return heap->isolate()->Throw( | 7216 return heap->isolate()->Throw( |
| 7190 *FACTORY->NewTypeError("object_not_extensible", | 7217 *FACTORY->NewTypeError("object_not_extensible", |
| 7191 HandleVector(args, 1))); | 7218 HandleVector(args, 1))); |
| (...skipping 977 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8169 return Isolate::Current()->heap()->AllocateSymbol( | 8196 return Isolate::Current()->heap()->AllocateSymbol( |
| 8170 string_, chars_, hash_field_); | 8197 string_, chars_, hash_field_); |
| 8171 } | 8198 } |
| 8172 | 8199 |
| 8173 Vector<const char> string_; | 8200 Vector<const char> string_; |
| 8174 uint32_t hash_field_; | 8201 uint32_t hash_field_; |
| 8175 int chars_; // Caches the number of characters when computing the hash code. | 8202 int chars_; // Caches the number of characters when computing the hash code. |
| 8176 }; | 8203 }; |
| 8177 | 8204 |
| 8178 | 8205 |
| 8206 template <typename Char> |
| 8207 class SequentialSymbolKey : public HashTableKey { |
| 8208 public: |
| 8209 explicit SequentialSymbolKey(Vector<const Char> string) |
| 8210 : string_(string), hash_field_(0) { } |
| 8211 |
| 8212 uint32_t Hash() { |
| 8213 StringHasher hasher(string_.length()); |
| 8214 |
| 8215 // Very long strings have a trivial hash that doesn't inspect the |
| 8216 // string contents. |
| 8217 if (hasher.has_trivial_hash()) { |
| 8218 hash_field_ = hasher.GetHashField(); |
| 8219 } else { |
| 8220 int i = 0; |
| 8221 // Do the iterative array index computation as long as there is a |
| 8222 // chance this is an array index. |
| 8223 while (i < string_.length() && hasher.is_array_index()) { |
| 8224 hasher.AddCharacter(static_cast<uc32>(string_[i])); |
| 8225 i++; |
| 8226 } |
| 8227 |
| 8228 // Process the remaining characters without updating the array |
| 8229 // index. |
| 8230 while (i < string_.length()) { |
| 8231 hasher.AddCharacterNoIndex(static_cast<uc32>(string_[i])); |
| 8232 i++; |
| 8233 } |
| 8234 hash_field_ = hasher.GetHashField(); |
| 8235 } |
| 8236 |
| 8237 uint32_t result = hash_field_ >> String::kHashShift; |
| 8238 ASSERT(result != 0); // Ensure that the hash value of 0 is never computed. |
| 8239 return result; |
| 8240 } |
| 8241 |
| 8242 |
| 8243 uint32_t HashForObject(Object* other) { |
| 8244 return String::cast(other)->Hash(); |
| 8245 } |
| 8246 |
| 8247 Vector<const Char> string_; |
| 8248 uint32_t hash_field_; |
| 8249 }; |
| 8250 |
| 8251 |
| 8252 |
| 8253 class AsciiSymbolKey : public SequentialSymbolKey<char> { |
| 8254 public: |
| 8255 explicit AsciiSymbolKey(Vector<const char> str) |
| 8256 : SequentialSymbolKey<char>(str) { } |
| 8257 |
| 8258 bool IsMatch(Object* string) { |
| 8259 return String::cast(string)->IsAsciiEqualTo(string_); |
| 8260 } |
| 8261 |
| 8262 MaybeObject* AsObject() { |
| 8263 if (hash_field_ == 0) Hash(); |
| 8264 return HEAP->AllocateAsciiSymbol(string_, hash_field_); |
| 8265 } |
| 8266 }; |
| 8267 |
| 8268 |
| 8269 class TwoByteSymbolKey : public SequentialSymbolKey<uc16> { |
| 8270 public: |
| 8271 explicit TwoByteSymbolKey(Vector<const uc16> str) |
| 8272 : SequentialSymbolKey<uc16>(str) { } |
| 8273 |
| 8274 bool IsMatch(Object* string) { |
| 8275 return String::cast(string)->IsTwoByteEqualTo(string_); |
| 8276 } |
| 8277 |
| 8278 MaybeObject* AsObject() { |
| 8279 if (hash_field_ == 0) Hash(); |
| 8280 return HEAP->AllocateTwoByteSymbol(string_, hash_field_); |
| 8281 } |
| 8282 }; |
| 8283 |
| 8284 |
| 8179 // SymbolKey carries a string/symbol object as key. | 8285 // SymbolKey carries a string/symbol object as key. |
| 8180 class SymbolKey : public HashTableKey { | 8286 class SymbolKey : public HashTableKey { |
| 8181 public: | 8287 public: |
| 8182 explicit SymbolKey(String* string) | 8288 explicit SymbolKey(String* string) |
| 8183 : string_(string) { } | 8289 : string_(string) { } |
| 8184 | 8290 |
| 8185 bool IsMatch(Object* string) { | 8291 bool IsMatch(Object* string) { |
| 8186 return String::cast(string)->Equals(string_); | 8292 return String::cast(string)->Equals(string_); |
| 8187 } | 8293 } |
| 8188 | 8294 |
| (...skipping 716 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8905 } | 9011 } |
| 8906 } | 9012 } |
| 8907 | 9013 |
| 8908 | 9014 |
| 8909 MaybeObject* SymbolTable::LookupSymbol(Vector<const char> str, Object** s) { | 9015 MaybeObject* SymbolTable::LookupSymbol(Vector<const char> str, Object** s) { |
| 8910 Utf8SymbolKey key(str); | 9016 Utf8SymbolKey key(str); |
| 8911 return LookupKey(&key, s); | 9017 return LookupKey(&key, s); |
| 8912 } | 9018 } |
| 8913 | 9019 |
| 8914 | 9020 |
| 9021 MaybeObject* SymbolTable::LookupAsciiSymbol(Vector<const char> str, |
| 9022 Object** s) { |
| 9023 AsciiSymbolKey key(str); |
| 9024 return LookupKey(&key, s); |
| 9025 } |
| 9026 |
| 9027 |
| 9028 MaybeObject* SymbolTable::LookupTwoByteSymbol(Vector<const uc16> str, |
| 9029 Object** s) { |
| 9030 TwoByteSymbolKey key(str); |
| 9031 return LookupKey(&key, s); |
| 9032 } |
| 9033 |
| 8915 MaybeObject* SymbolTable::LookupKey(HashTableKey* key, Object** s) { | 9034 MaybeObject* SymbolTable::LookupKey(HashTableKey* key, Object** s) { |
| 8916 int entry = FindEntry(key); | 9035 int entry = FindEntry(key); |
| 8917 | 9036 |
| 8918 // Symbol already in table. | 9037 // Symbol already in table. |
| 8919 if (entry != kNotFound) { | 9038 if (entry != kNotFound) { |
| 8920 *s = KeyAt(entry); | 9039 *s = KeyAt(entry); |
| 8921 return this; | 9040 return this; |
| 8922 } | 9041 } |
| 8923 | 9042 |
| 8924 // Adding new symbol. Grow table if needed. | 9043 // Adding new symbol. Grow table if needed. |
| (...skipping 921 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9846 if (break_point_objects()->IsUndefined()) return 0; | 9965 if (break_point_objects()->IsUndefined()) return 0; |
| 9847 // Single beak point. | 9966 // Single beak point. |
| 9848 if (!break_point_objects()->IsFixedArray()) return 1; | 9967 if (!break_point_objects()->IsFixedArray()) return 1; |
| 9849 // Multiple break points. | 9968 // Multiple break points. |
| 9850 return FixedArray::cast(break_point_objects())->length(); | 9969 return FixedArray::cast(break_point_objects())->length(); |
| 9851 } | 9970 } |
| 9852 #endif | 9971 #endif |
| 9853 | 9972 |
| 9854 | 9973 |
| 9855 } } // namespace v8::internal | 9974 } } // namespace v8::internal |
| OLD | NEW |