| OLD | NEW |
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 53 #endif | 53 #endif |
| 54 | 54 |
| 55 namespace v8 { | 55 namespace v8 { |
| 56 namespace internal { | 56 namespace internal { |
| 57 | 57 |
| 58 // Getters and setters are stored in a fixed array property. These are | 58 // Getters and setters are stored in a fixed array property. These are |
| 59 // constants for their indices. | 59 // constants for their indices. |
| 60 const int kGetterIndex = 0; | 60 const int kGetterIndex = 0; |
| 61 const int kSetterIndex = 1; | 61 const int kSetterIndex = 1; |
| 62 | 62 |
| 63 uint64_t FixedDoubleArray::kHoleNanInt64 = -1; | |
| 64 uint64_t FixedDoubleArray::kCanonicalNonHoleNanLower32 = 0x7FF00000; | |
| 65 uint64_t FixedDoubleArray::kCanonicalNonHoleNanInt64 = | |
| 66 kCanonicalNonHoleNanLower32 << 32; | |
| 67 | |
| 68 MUST_USE_RESULT static MaybeObject* CreateJSValue(JSFunction* constructor, | 63 MUST_USE_RESULT static MaybeObject* CreateJSValue(JSFunction* constructor, |
| 69 Object* value) { | 64 Object* value) { |
| 70 Object* result; | 65 Object* result; |
| 71 { MaybeObject* maybe_result = | 66 { MaybeObject* maybe_result = |
| 72 constructor->GetHeap()->AllocateJSObject(constructor); | 67 constructor->GetHeap()->AllocateJSObject(constructor); |
| 73 if (!maybe_result->ToObject(&result)) return maybe_result; | 68 if (!maybe_result->ToObject(&result)) return maybe_result; |
| 74 } | 69 } |
| 75 JSValue::cast(result)->set_value(value); | 70 JSValue::cast(result)->set_value(value); |
| 76 return result; | 71 return result; |
| 77 } | 72 } |
| (...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 189 MaybeObject* value = (callback->getter)(receiver, callback->data); | 184 MaybeObject* value = (callback->getter)(receiver, callback->data); |
| 190 RETURN_IF_SCHEDULED_EXCEPTION(isolate); | 185 RETURN_IF_SCHEDULED_EXCEPTION(isolate); |
| 191 return value; | 186 return value; |
| 192 } | 187 } |
| 193 | 188 |
| 194 // api style callbacks. | 189 // api style callbacks. |
| 195 if (structure->IsAccessorInfo()) { | 190 if (structure->IsAccessorInfo()) { |
| 196 AccessorInfo* data = AccessorInfo::cast(structure); | 191 AccessorInfo* data = AccessorInfo::cast(structure); |
| 197 Object* fun_obj = data->getter(); | 192 Object* fun_obj = data->getter(); |
| 198 v8::AccessorGetter call_fun = v8::ToCData<v8::AccessorGetter>(fun_obj); | 193 v8::AccessorGetter call_fun = v8::ToCData<v8::AccessorGetter>(fun_obj); |
| 199 HandleScope scope; | 194 HandleScope scope(isolate); |
| 200 JSObject* self = JSObject::cast(receiver); | 195 JSObject* self = JSObject::cast(receiver); |
| 201 JSObject* holder_handle = JSObject::cast(holder); | 196 JSObject* holder_handle = JSObject::cast(holder); |
| 202 Handle<String> key(name); | 197 Handle<String> key(name); |
| 203 LOG(isolate, ApiNamedPropertyAccess("load", self, name)); | 198 LOG(isolate, ApiNamedPropertyAccess("load", self, name)); |
| 204 CustomArguments args(isolate, data->data(), self, holder_handle); | 199 CustomArguments args(isolate, data->data(), self, holder_handle); |
| 205 v8::AccessorInfo info(args.end()); | 200 v8::AccessorInfo info(args.end()); |
| 206 v8::Handle<v8::Value> result; | 201 v8::Handle<v8::Value> result; |
| 207 { | 202 { |
| 208 // Leaving JavaScript. | 203 // Leaving JavaScript. |
| 209 VMState state(isolate, EXTERNAL); | 204 VMState state(isolate, EXTERNAL); |
| (...skipping 19 matching lines...) Expand all Loading... |
| 229 | 224 |
| 230 UNREACHABLE(); | 225 UNREACHABLE(); |
| 231 return NULL; | 226 return NULL; |
| 232 } | 227 } |
| 233 | 228 |
| 234 | 229 |
| 235 MaybeObject* Object::GetPropertyWithHandler(Object* receiver_raw, | 230 MaybeObject* Object::GetPropertyWithHandler(Object* receiver_raw, |
| 236 String* name_raw, | 231 String* name_raw, |
| 237 Object* handler_raw) { | 232 Object* handler_raw) { |
| 238 Isolate* isolate = name_raw->GetIsolate(); | 233 Isolate* isolate = name_raw->GetIsolate(); |
| 239 HandleScope scope; | 234 HandleScope scope(isolate); |
| 240 Handle<Object> receiver(receiver_raw); | 235 Handle<Object> receiver(receiver_raw); |
| 241 Handle<Object> name(name_raw); | 236 Handle<Object> name(name_raw); |
| 242 Handle<Object> handler(handler_raw); | 237 Handle<Object> handler(handler_raw); |
| 243 | 238 |
| 244 // Extract trap function. | 239 // Extract trap function. |
| 245 Handle<String> trap_name = isolate->factory()->LookupAsciiSymbol("get"); | 240 Handle<String> trap_name = isolate->factory()->LookupAsciiSymbol("get"); |
| 246 Handle<Object> trap(v8::internal::GetProperty(handler, trap_name)); | 241 Handle<Object> trap(v8::internal::GetProperty(handler, trap_name)); |
| 247 if (trap->IsUndefined()) { | 242 if (trap->IsUndefined()) { |
| 248 // Get the derived `get' property. | 243 // Get the derived `get' property. |
| 249 trap = isolate->derived_get_trap(); | 244 trap = isolate->derived_get_trap(); |
| (...skipping 1639 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1889 | 1884 |
| 1890 | 1885 |
| 1891 void JSObject::LookupCallbackSetterInPrototypes(String* name, | 1886 void JSObject::LookupCallbackSetterInPrototypes(String* name, |
| 1892 LookupResult* result) { | 1887 LookupResult* result) { |
| 1893 Heap* heap = GetHeap(); | 1888 Heap* heap = GetHeap(); |
| 1894 for (Object* pt = GetPrototype(); | 1889 for (Object* pt = GetPrototype(); |
| 1895 pt != heap->null_value(); | 1890 pt != heap->null_value(); |
| 1896 pt = pt->GetPrototype()) { | 1891 pt = pt->GetPrototype()) { |
| 1897 JSObject::cast(pt)->LocalLookupRealNamedProperty(name, result); | 1892 JSObject::cast(pt)->LocalLookupRealNamedProperty(name, result); |
| 1898 if (result->IsProperty()) { | 1893 if (result->IsProperty()) { |
| 1899 if (result->IsReadOnly()) { | 1894 if (result->type() == CALLBACKS && !result->IsReadOnly()) return; |
| 1900 result->NotFound(); | 1895 // Found non-callback or read-only callback, stop looking. |
| 1901 return; | 1896 break; |
| 1902 } | |
| 1903 if (result->type() == CALLBACKS) { | |
| 1904 return; | |
| 1905 } | |
| 1906 } | 1897 } |
| 1907 } | 1898 } |
| 1908 result->NotFound(); | 1899 result->NotFound(); |
| 1909 } | 1900 } |
| 1910 | 1901 |
| 1911 | 1902 |
| 1912 MaybeObject* JSObject::SetElementWithCallbackSetterInPrototypes( | 1903 MaybeObject* JSObject::SetElementWithCallbackSetterInPrototypes( |
| 1913 uint32_t index, | 1904 uint32_t index, |
| 1914 Object* value, | 1905 Object* value, |
| 1915 bool* found, | 1906 bool* found, |
| (...skipping 273 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2189 } | 2180 } |
| 2190 break; | 2181 break; |
| 2191 } | 2182 } |
| 2192 default: { | 2183 default: { |
| 2193 break; | 2184 break; |
| 2194 } | 2185 } |
| 2195 } | 2186 } |
| 2196 } | 2187 } |
| 2197 } | 2188 } |
| 2198 | 2189 |
| 2199 HandleScope scope; | 2190 Heap* heap = GetHeap(); |
| 2191 HandleScope scope(heap->isolate()); |
| 2200 Handle<Object> value_handle(value); | 2192 Handle<Object> value_handle(value); |
| 2201 Heap* heap = GetHeap(); | |
| 2202 heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_SET); | 2193 heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_SET); |
| 2203 return *value_handle; | 2194 return *value_handle; |
| 2204 } | 2195 } |
| 2205 | 2196 |
| 2206 | 2197 |
| 2207 MaybeObject* JSReceiver::SetProperty(LookupResult* result, | 2198 MaybeObject* JSReceiver::SetProperty(LookupResult* result, |
| 2208 String* key, | 2199 String* key, |
| 2209 Object* value, | 2200 Object* value, |
| 2210 PropertyAttributes attributes, | 2201 PropertyAttributes attributes, |
| 2211 StrictModeFlag strict_mode) { | 2202 StrictModeFlag strict_mode) { |
| 2212 if (result->IsFound() && result->type() == HANDLER) { | 2203 if (result->IsFound() && result->type() == HANDLER) { |
| 2213 return JSProxy::cast(this)->SetPropertyWithHandler( | 2204 return JSProxy::cast(this)->SetPropertyWithHandler( |
| 2214 key, value, attributes, strict_mode); | 2205 key, value, attributes, strict_mode); |
| 2215 } else { | 2206 } else { |
| 2216 return JSObject::cast(this)->SetPropertyForResult( | 2207 return JSObject::cast(this)->SetPropertyForResult( |
| 2217 result, key, value, attributes, strict_mode); | 2208 result, key, value, attributes, strict_mode); |
| 2218 } | 2209 } |
| 2219 } | 2210 } |
| 2220 | 2211 |
| 2221 | 2212 |
| 2213 bool JSProxy::HasPropertyWithHandler(String* name_raw) { |
| 2214 Isolate* isolate = GetIsolate(); |
| 2215 HandleScope scope(isolate); |
| 2216 Handle<Object> receiver(this); |
| 2217 Handle<Object> name(name_raw); |
| 2218 Handle<Object> handler(this->handler()); |
| 2219 |
| 2220 // Extract trap function. |
| 2221 Handle<String> trap_name = isolate->factory()->LookupAsciiSymbol("has"); |
| 2222 Handle<Object> trap(v8::internal::GetProperty(handler, trap_name)); |
| 2223 if (trap->IsUndefined()) { |
| 2224 trap = isolate->derived_has_trap(); |
| 2225 } |
| 2226 |
| 2227 // Call trap function. |
| 2228 Object** args[] = { name.location() }; |
| 2229 bool has_exception; |
| 2230 Handle<Object> result = |
| 2231 Execution::Call(trap, handler, ARRAY_SIZE(args), args, &has_exception); |
| 2232 if (has_exception) return Failure::Exception(); |
| 2233 |
| 2234 return result->ToBoolean()->IsTrue(); |
| 2235 } |
| 2236 |
| 2237 |
| 2222 MUST_USE_RESULT MaybeObject* JSProxy::SetPropertyWithHandler( | 2238 MUST_USE_RESULT MaybeObject* JSProxy::SetPropertyWithHandler( |
| 2223 String* name_raw, | 2239 String* name_raw, |
| 2224 Object* value_raw, | 2240 Object* value_raw, |
| 2225 PropertyAttributes attributes, | 2241 PropertyAttributes attributes, |
| 2226 StrictModeFlag strict_mode) { | 2242 StrictModeFlag strict_mode) { |
| 2227 Isolate* isolate = GetIsolate(); | 2243 Isolate* isolate = GetIsolate(); |
| 2228 HandleScope scope; | 2244 HandleScope scope(isolate); |
| 2229 Handle<Object> receiver(this); | 2245 Handle<Object> receiver(this); |
| 2230 Handle<Object> name(name_raw); | 2246 Handle<Object> name(name_raw); |
| 2231 Handle<Object> value(value_raw); | 2247 Handle<Object> value(value_raw); |
| 2232 Handle<Object> handler(this->handler()); | 2248 Handle<Object> handler(this->handler()); |
| 2233 | 2249 |
| 2234 // Extract trap function. | 2250 // Extract trap function. |
| 2235 Handle<String> trap_name = isolate->factory()->LookupAsciiSymbol("set"); | 2251 Handle<String> trap_name = isolate->factory()->LookupAsciiSymbol("set"); |
| 2236 Handle<Object> trap(v8::internal::GetProperty(handler, trap_name)); | 2252 Handle<Object> trap(v8::internal::GetProperty(handler, trap_name)); |
| 2237 if (trap->IsUndefined()) { | 2253 if (trap->IsUndefined()) { |
| 2238 trap = isolate->derived_set_trap(); | 2254 trap = isolate->derived_set_trap(); |
| 2239 } | 2255 } |
| 2240 | 2256 |
| 2241 // Call trap function. | 2257 // Call trap function. |
| 2242 Object** args[] = { | 2258 Object** args[] = { |
| 2243 receiver.location(), name.location(), value.location() | 2259 receiver.location(), name.location(), value.location() |
| 2244 }; | 2260 }; |
| 2245 bool has_exception; | 2261 bool has_exception; |
| 2246 Handle<Object> result = | 2262 Execution::Call(trap, handler, ARRAY_SIZE(args), args, &has_exception); |
| 2247 Execution::Call(trap, handler, ARRAY_SIZE(args), args, &has_exception); | |
| 2248 if (has_exception) return Failure::Exception(); | 2263 if (has_exception) return Failure::Exception(); |
| 2249 | 2264 |
| 2250 return *value; | 2265 return *value; |
| 2251 } | 2266 } |
| 2252 | 2267 |
| 2253 | 2268 |
| 2269 MUST_USE_RESULT MaybeObject* JSProxy::DeletePropertyWithHandler( |
| 2270 String* name_raw, DeleteMode mode) { |
| 2271 Isolate* isolate = GetIsolate(); |
| 2272 HandleScope scope(isolate); |
| 2273 Handle<Object> receiver(this); |
| 2274 Handle<Object> name(name_raw); |
| 2275 Handle<Object> handler(this->handler()); |
| 2276 |
| 2277 // Extract trap function. |
| 2278 Handle<String> trap_name = isolate->factory()->LookupAsciiSymbol("delete"); |
| 2279 Handle<Object> trap(v8::internal::GetProperty(handler, trap_name)); |
| 2280 if (trap->IsUndefined()) { |
| 2281 Handle<Object> args[] = { handler, trap_name }; |
| 2282 Handle<Object> error = isolate->factory()->NewTypeError( |
| 2283 "handler_trap_missing", HandleVector(args, ARRAY_SIZE(args))); |
| 2284 isolate->Throw(*error); |
| 2285 return Failure::Exception(); |
| 2286 } |
| 2287 |
| 2288 // Call trap function. |
| 2289 Object** args[] = { name.location() }; |
| 2290 bool has_exception; |
| 2291 Handle<Object> result = |
| 2292 Execution::Call(trap, handler, ARRAY_SIZE(args), args, &has_exception); |
| 2293 if (has_exception) return Failure::Exception(); |
| 2294 |
| 2295 Object* bool_result = result->ToBoolean(); |
| 2296 if (mode == STRICT_DELETION && bool_result == GetHeap()->false_value()) { |
| 2297 Handle<Object> args[] = { handler, trap_name }; |
| 2298 Handle<Object> error = isolate->factory()->NewTypeError( |
| 2299 "handler_failed", HandleVector(args, ARRAY_SIZE(args))); |
| 2300 isolate->Throw(*error); |
| 2301 return Failure::Exception(); |
| 2302 } |
| 2303 return bool_result; |
| 2304 } |
| 2305 |
| 2306 |
| 2254 MUST_USE_RESULT PropertyAttributes JSProxy::GetPropertyAttributeWithHandler( | 2307 MUST_USE_RESULT PropertyAttributes JSProxy::GetPropertyAttributeWithHandler( |
| 2255 JSReceiver* receiver_raw, | 2308 JSReceiver* receiver_raw, |
| 2256 String* name_raw, | 2309 String* name_raw, |
| 2257 bool* has_exception) { | 2310 bool* has_exception) { |
| 2258 Isolate* isolate = GetIsolate(); | 2311 Isolate* isolate = GetIsolate(); |
| 2259 HandleScope scope; | 2312 HandleScope scope(isolate); |
| 2260 Handle<JSReceiver> receiver(receiver_raw); | 2313 Handle<JSReceiver> receiver(receiver_raw); |
| 2261 Handle<Object> name(name_raw); | 2314 Handle<Object> name(name_raw); |
| 2262 Handle<Object> handler(this->handler()); | 2315 Handle<Object> handler(this->handler()); |
| 2263 | 2316 |
| 2264 // Extract trap function. | 2317 // Extract trap function. |
| 2265 Handle<String> trap_name = | 2318 Handle<String> trap_name = |
| 2266 isolate->factory()->LookupAsciiSymbol("getPropertyDescriptor"); | 2319 isolate->factory()->LookupAsciiSymbol("getPropertyDescriptor"); |
| 2267 Handle<Object> trap(v8::internal::GetProperty(handler, trap_name)); | 2320 Handle<Object> trap(v8::internal::GetProperty(handler, trap_name)); |
| 2268 if (trap->IsUndefined()) { | 2321 if (trap->IsUndefined()) { |
| 2269 Handle<Object> args[] = { handler, trap_name }; | 2322 Handle<Object> args[] = { handler, trap_name }; |
| 2270 Handle<Object> error = isolate->factory()->NewTypeError( | 2323 Handle<Object> error = isolate->factory()->NewTypeError( |
| 2271 "handler_trap_missing", HandleVector(args, ARRAY_SIZE(args))); | 2324 "handler_trap_missing", HandleVector(args, ARRAY_SIZE(args))); |
| 2272 isolate->Throw(*error); | 2325 isolate->Throw(*error); |
| 2273 *has_exception = true; | 2326 *has_exception = true; |
| 2274 return NONE; | 2327 return NONE; |
| 2275 } | 2328 } |
| 2276 | 2329 |
| 2277 // Call trap function. | 2330 // Call trap function. |
| 2278 Object** args[] = { name.location() }; | 2331 Object** args[] = { name.location() }; |
| 2279 Handle<Object> result = | 2332 Handle<Object> result = |
| 2280 Execution::Call(trap, handler, ARRAY_SIZE(args), args, has_exception); | 2333 Execution::Call(trap, handler, ARRAY_SIZE(args), args, has_exception); |
| 2281 if (has_exception) return NONE; | 2334 if (has_exception) return NONE; |
| 2282 | 2335 |
| 2283 // TODO(rossberg): convert result to PropertyAttributes | 2336 // TODO(rossberg): convert result to PropertyAttributes |
| 2284 USE(result); | 2337 USE(result); |
| 2285 return NONE; | 2338 return NONE; |
| 2286 } | 2339 } |
| 2287 | 2340 |
| 2288 | 2341 |
| 2342 void JSProxy::Fix() { |
| 2343 Isolate* isolate = GetIsolate(); |
| 2344 HandleScope scope(isolate); |
| 2345 Handle<JSProxy> self(this); |
| 2346 |
| 2347 isolate->factory()->BecomeJSObject(self); |
| 2348 ASSERT(self->IsJSObject()); |
| 2349 // TODO(rossberg): recognize function proxies. |
| 2350 } |
| 2351 |
| 2352 |
| 2353 |
| 2289 MaybeObject* JSObject::SetPropertyForResult(LookupResult* result, | 2354 MaybeObject* JSObject::SetPropertyForResult(LookupResult* result, |
| 2290 String* name, | 2355 String* name, |
| 2291 Object* value, | 2356 Object* value, |
| 2292 PropertyAttributes attributes, | 2357 PropertyAttributes attributes, |
| 2293 StrictModeFlag strict_mode) { | 2358 StrictModeFlag strict_mode) { |
| 2294 Heap* heap = GetHeap(); | 2359 Heap* heap = GetHeap(); |
| 2295 // Make sure that the top context does not change when doing callbacks or | 2360 // Make sure that the top context does not change when doing callbacks or |
| 2296 // interceptor calls. | 2361 // interceptor calls. |
| 2297 AssertNoContextChange ncc; | 2362 AssertNoContextChange ncc; |
| 2298 | 2363 |
| 2299 // Optimization for 2-byte strings often used as keys in a decompression | 2364 // Optimization for 2-byte strings often used as keys in a decompression |
| 2300 // dictionary. We make these short keys into symbols to avoid constantly | 2365 // dictionary. We make these short keys into symbols to avoid constantly |
| 2301 // reallocating them. | 2366 // reallocating them. |
| 2302 if (!name->IsSymbol() && name->length() <= 2) { | 2367 if (!name->IsSymbol() && name->length() <= 2) { |
| 2303 Object* symbol_version; | 2368 Object* symbol_version; |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2338 accessor_result.holder(), | 2403 accessor_result.holder(), |
| 2339 strict_mode); | 2404 strict_mode); |
| 2340 } | 2405 } |
| 2341 } | 2406 } |
| 2342 if (!result->IsFound()) { | 2407 if (!result->IsFound()) { |
| 2343 // Neither properties nor transitions found. | 2408 // Neither properties nor transitions found. |
| 2344 return AddProperty(name, value, attributes, strict_mode); | 2409 return AddProperty(name, value, attributes, strict_mode); |
| 2345 } | 2410 } |
| 2346 if (result->IsReadOnly() && result->IsProperty()) { | 2411 if (result->IsReadOnly() && result->IsProperty()) { |
| 2347 if (strict_mode == kStrictMode) { | 2412 if (strict_mode == kStrictMode) { |
| 2348 HandleScope scope; | 2413 HandleScope scope(heap->isolate()); |
| 2349 Handle<String> key(name); | 2414 Handle<String> key(name); |
| 2350 Handle<Object> holder(this); | 2415 Handle<Object> holder(this); |
| 2351 Handle<Object> args[2] = { key, holder }; | 2416 Handle<Object> args[2] = { key, holder }; |
| 2352 return heap->isolate()->Throw(*heap->isolate()->factory()->NewTypeError( | 2417 return heap->isolate()->Throw(*heap->isolate()->factory()->NewTypeError( |
| 2353 "strict_read_only_property", HandleVector(args, 2))); | 2418 "strict_read_only_property", HandleVector(args, 2))); |
| 2354 } else { | 2419 } else { |
| 2355 return value; | 2420 return value; |
| 2356 } | 2421 } |
| 2357 } | 2422 } |
| 2358 // This is a real property that is not read-only, or it is a | 2423 // This is a real property that is not read-only, or it is a |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2413 return value; | 2478 return value; |
| 2414 } | 2479 } |
| 2415 | 2480 |
| 2416 | 2481 |
| 2417 // Set a real local property, even if it is READ_ONLY. If the property is not | 2482 // Set a real local property, even if it is READ_ONLY. If the property is not |
| 2418 // present, add it with attributes NONE. This code is an exact clone of | 2483 // present, add it with attributes NONE. This code is an exact clone of |
| 2419 // SetProperty, with the check for IsReadOnly and the check for a | 2484 // SetProperty, with the check for IsReadOnly and the check for a |
| 2420 // callback setter removed. The two lines looking up the LookupResult | 2485 // callback setter removed. The two lines looking up the LookupResult |
| 2421 // result are also added. If one of the functions is changed, the other | 2486 // result are also added. If one of the functions is changed, the other |
| 2422 // should be. | 2487 // should be. |
| 2488 // Note that this method cannot be used to set the prototype of a function |
| 2489 // because ConvertDescriptorToField() which is called in "case CALLBACKS:" |
| 2490 // doesn't handle function prototypes correctly. |
| 2423 MaybeObject* JSObject::SetLocalPropertyIgnoreAttributes( | 2491 MaybeObject* JSObject::SetLocalPropertyIgnoreAttributes( |
| 2424 String* name, | 2492 String* name, |
| 2425 Object* value, | 2493 Object* value, |
| 2426 PropertyAttributes attributes) { | 2494 PropertyAttributes attributes) { |
| 2427 | 2495 |
| 2428 // Make sure that the top context does not change when doing callbacks or | 2496 // Make sure that the top context does not change when doing callbacks or |
| 2429 // interceptor calls. | 2497 // interceptor calls. |
| 2430 AssertNoContextChange ncc; | 2498 AssertNoContextChange ncc; |
| 2431 LookupResult result; | 2499 LookupResult result; |
| 2432 LocalLookup(name, &result); | 2500 LocalLookup(name, &result); |
| (...skipping 393 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2826 ASSERT(!IsGlobalObject()); | 2894 ASSERT(!IsGlobalObject()); |
| 2827 return property_dictionary()-> | 2895 return property_dictionary()-> |
| 2828 TransformPropertiesToFastFor(this, unused_property_fields); | 2896 TransformPropertiesToFastFor(this, unused_property_fields); |
| 2829 } | 2897 } |
| 2830 | 2898 |
| 2831 | 2899 |
| 2832 MaybeObject* JSObject::NormalizeElements() { | 2900 MaybeObject* JSObject::NormalizeElements() { |
| 2833 ASSERT(!HasExternalArrayElements()); | 2901 ASSERT(!HasExternalArrayElements()); |
| 2834 | 2902 |
| 2835 // Find the backing store. | 2903 // Find the backing store. |
| 2836 FixedArray* array = FixedArray::cast(elements()); | 2904 FixedArrayBase* array = FixedArrayBase::cast(elements()); |
| 2837 Map* old_map = array->map(); | 2905 Map* old_map = array->map(); |
| 2838 bool is_arguments = | 2906 bool is_arguments = |
| 2839 (old_map == old_map->GetHeap()->non_strict_arguments_elements_map()); | 2907 (old_map == old_map->GetHeap()->non_strict_arguments_elements_map()); |
| 2840 if (is_arguments) { | 2908 if (is_arguments) { |
| 2841 array = FixedArray::cast(array->get(1)); | 2909 array = FixedArrayBase::cast(FixedArray::cast(array)->get(1)); |
| 2842 } | 2910 } |
| 2843 if (array->IsDictionary()) return array; | 2911 if (array->IsDictionary()) return array; |
| 2844 | 2912 |
| 2845 ASSERT(HasFastElements() || HasFastArgumentsElements()); | 2913 ASSERT(HasFastElements() || |
| 2914 HasFastDoubleElements() || |
| 2915 HasFastArgumentsElements()); |
| 2846 // Compute the effective length and allocate a new backing store. | 2916 // Compute the effective length and allocate a new backing store. |
| 2847 int length = IsJSArray() | 2917 int length = IsJSArray() |
| 2848 ? Smi::cast(JSArray::cast(this)->length())->value() | 2918 ? Smi::cast(JSArray::cast(this)->length())->value() |
| 2849 : array->length(); | 2919 : array->length(); |
| 2920 int old_capacity = 0; |
| 2921 int used_elements = 0; |
| 2922 GetElementsCapacityAndUsage(&old_capacity, &used_elements); |
| 2850 NumberDictionary* dictionary = NULL; | 2923 NumberDictionary* dictionary = NULL; |
| 2851 { Object* object; | 2924 { Object* object; |
| 2852 MaybeObject* maybe = NumberDictionary::Allocate(length); | 2925 MaybeObject* maybe = NumberDictionary::Allocate(used_elements); |
| 2853 if (!maybe->ToObject(&object)) return maybe; | 2926 if (!maybe->ToObject(&object)) return maybe; |
| 2854 dictionary = NumberDictionary::cast(object); | 2927 dictionary = NumberDictionary::cast(object); |
| 2855 } | 2928 } |
| 2856 | 2929 |
| 2857 // Copy the elements to the new backing store. | 2930 // Copy the elements to the new backing store. |
| 2858 bool has_double_elements = old_map->has_fast_double_elements(); | 2931 bool has_double_elements = array->IsFixedDoubleArray(); |
| 2859 for (int i = 0; i < length; i++) { | 2932 for (int i = 0; i < length; i++) { |
| 2860 Object* value = NULL; | 2933 Object* value = NULL; |
| 2861 if (has_double_elements) { | 2934 if (has_double_elements) { |
| 2862 FixedDoubleArray* double_array = FixedDoubleArray::cast(array); | 2935 FixedDoubleArray* double_array = FixedDoubleArray::cast(array); |
| 2863 if (double_array->is_the_hole(i)) { | 2936 if (double_array->is_the_hole(i)) { |
| 2864 value = GetIsolate()->heap()->the_hole_value(); | 2937 value = GetIsolate()->heap()->the_hole_value(); |
| 2865 } else { | 2938 } else { |
| 2866 // Objects must be allocated in the old object space, since the | 2939 // Objects must be allocated in the old object space, since the |
| 2867 // overall number of HeapNumbers needed for the conversion might | 2940 // overall number of HeapNumbers needed for the conversion might |
| 2868 // exceed the capacity of new space, and we would fail repeatedly | 2941 // exceed the capacity of new space, and we would fail repeatedly |
| 2869 // trying to convert the FixedDoubleArray. | 2942 // trying to convert the FixedDoubleArray. |
| 2870 MaybeObject* maybe_value_object = | 2943 MaybeObject* maybe_value_object = |
| 2871 GetHeap()->AllocateHeapNumber(double_array->get(i), TENURED); | 2944 GetHeap()->AllocateHeapNumber(double_array->get(i), TENURED); |
| 2872 if (!maybe_value_object->ToObject(&value)) return maybe_value_object; | 2945 if (!maybe_value_object->ToObject(&value)) return maybe_value_object; |
| 2873 } | 2946 } |
| 2874 } else { | 2947 } else { |
| 2875 ASSERT(old_map->has_fast_elements()); | 2948 ASSERT(old_map->has_fast_elements()); |
| 2876 value = array->get(i); | 2949 value = FixedArray::cast(array)->get(i); |
| 2877 } | 2950 } |
| 2878 PropertyDetails details = PropertyDetails(NONE, NORMAL); | 2951 PropertyDetails details = PropertyDetails(NONE, NORMAL); |
| 2879 if (!value->IsTheHole()) { | 2952 if (!value->IsTheHole()) { |
| 2880 Object* result; | 2953 Object* result; |
| 2881 MaybeObject* maybe_result = | 2954 MaybeObject* maybe_result = |
| 2882 dictionary->AddNumberEntry(i, value, details); | 2955 dictionary->AddNumberEntry(i, value, details); |
| 2883 if (!maybe_result->ToObject(&result)) return maybe_result; | 2956 if (!maybe_result->ToObject(&result)) return maybe_result; |
| 2884 dictionary = NumberDictionary::cast(result); | 2957 dictionary = NumberDictionary::cast(result); |
| 2885 } | 2958 } |
| 2886 } | 2959 } |
| (...skipping 19 matching lines...) Expand all Loading... |
| 2906 PrintF("Object elements have been normalized:\n"); | 2979 PrintF("Object elements have been normalized:\n"); |
| 2907 Print(); | 2980 Print(); |
| 2908 } | 2981 } |
| 2909 #endif | 2982 #endif |
| 2910 | 2983 |
| 2911 ASSERT(HasDictionaryElements() || HasDictionaryArgumentsElements()); | 2984 ASSERT(HasDictionaryElements() || HasDictionaryArgumentsElements()); |
| 2912 return dictionary; | 2985 return dictionary; |
| 2913 } | 2986 } |
| 2914 | 2987 |
| 2915 | 2988 |
| 2989 MaybeObject* JSObject::GetHiddenProperties(HiddenPropertiesFlag flag) { |
| 2990 Isolate* isolate = GetIsolate(); |
| 2991 Heap* heap = isolate->heap(); |
| 2992 Object* holder = BypassGlobalProxy(); |
| 2993 if (holder->IsUndefined()) return heap->undefined_value(); |
| 2994 JSObject* obj = JSObject::cast(holder); |
| 2995 if (obj->HasFastProperties()) { |
| 2996 // If the object has fast properties, check whether the first slot |
| 2997 // in the descriptor array matches the hidden symbol. Since the |
| 2998 // hidden symbols hash code is zero (and no other string has hash |
| 2999 // code zero) it will always occupy the first entry if present. |
| 3000 DescriptorArray* descriptors = obj->map()->instance_descriptors(); |
| 3001 if ((descriptors->number_of_descriptors() > 0) && |
| 3002 (descriptors->GetKey(0) == heap->hidden_symbol()) && |
| 3003 descriptors->IsProperty(0)) { |
| 3004 ASSERT(descriptors->GetType(0) == FIELD); |
| 3005 return obj->FastPropertyAt(descriptors->GetFieldIndex(0)); |
| 3006 } |
| 3007 } |
| 3008 |
| 3009 // Only attempt to find the hidden properties in the local object and not |
| 3010 // in the prototype chain. |
| 3011 if (!obj->HasHiddenPropertiesObject()) { |
| 3012 // Hidden properties object not found. Allocate a new hidden properties |
| 3013 // object if requested. Otherwise return the undefined value. |
| 3014 if (flag == ALLOW_CREATION) { |
| 3015 Object* hidden_obj; |
| 3016 { MaybeObject* maybe_obj = heap->AllocateJSObject( |
| 3017 isolate->context()->global_context()->object_function()); |
| 3018 if (!maybe_obj->ToObject(&hidden_obj)) return maybe_obj; |
| 3019 } |
| 3020 return obj->SetHiddenPropertiesObject(hidden_obj); |
| 3021 } else { |
| 3022 return heap->undefined_value(); |
| 3023 } |
| 3024 } |
| 3025 return obj->GetHiddenPropertiesObject(); |
| 3026 } |
| 3027 |
| 3028 |
| 3029 MaybeObject* JSObject::GetIdentityHash(HiddenPropertiesFlag flag) { |
| 3030 Isolate* isolate = GetIsolate(); |
| 3031 Object* hidden_props_obj; |
| 3032 { MaybeObject* maybe_obj = GetHiddenProperties(flag); |
| 3033 if (!maybe_obj->ToObject(&hidden_props_obj)) return maybe_obj; |
| 3034 } |
| 3035 if (!hidden_props_obj->IsJSObject()) { |
| 3036 // We failed to create hidden properties. That's a detached |
| 3037 // global proxy. |
| 3038 ASSERT(hidden_props_obj->IsUndefined()); |
| 3039 return Smi::FromInt(0); |
| 3040 } |
| 3041 JSObject* hidden_props = JSObject::cast(hidden_props_obj); |
| 3042 String* hash_symbol = isolate->heap()->identity_hash_symbol(); |
| 3043 { |
| 3044 // Note that HasLocalProperty() can cause a GC in the general case in the |
| 3045 // presence of interceptors. |
| 3046 AssertNoAllocation no_alloc; |
| 3047 if (hidden_props->HasLocalProperty(hash_symbol)) { |
| 3048 MaybeObject* hash = hidden_props->GetProperty(hash_symbol); |
| 3049 return Smi::cast(hash->ToObjectChecked()); |
| 3050 } |
| 3051 } |
| 3052 |
| 3053 int hash_value; |
| 3054 int attempts = 0; |
| 3055 do { |
| 3056 // Generate a random 32-bit hash value but limit range to fit |
| 3057 // within a smi. |
| 3058 hash_value = V8::Random(isolate) & Smi::kMaxValue; |
| 3059 attempts++; |
| 3060 } while (hash_value == 0 && attempts < 30); |
| 3061 hash_value = hash_value != 0 ? hash_value : 1; // never return 0 |
| 3062 |
| 3063 Smi* hash = Smi::FromInt(hash_value); |
| 3064 { MaybeObject* result = hidden_props->SetLocalPropertyIgnoreAttributes( |
| 3065 hash_symbol, |
| 3066 hash, |
| 3067 static_cast<PropertyAttributes>(None)); |
| 3068 if (result->IsFailure()) return result; |
| 3069 } |
| 3070 return hash; |
| 3071 } |
| 3072 |
| 3073 |
| 2916 MaybeObject* JSObject::DeletePropertyPostInterceptor(String* name, | 3074 MaybeObject* JSObject::DeletePropertyPostInterceptor(String* name, |
| 2917 DeleteMode mode) { | 3075 DeleteMode mode) { |
| 2918 // Check local property, ignore interceptor. | 3076 // Check local property, ignore interceptor. |
| 2919 LookupResult result; | 3077 LookupResult result; |
| 2920 LocalLookupRealNamedProperty(name, &result); | 3078 LocalLookupRealNamedProperty(name, &result); |
| 2921 if (!result.IsProperty()) return GetHeap()->true_value(); | 3079 if (!result.IsProperty()) return GetHeap()->true_value(); |
| 2922 | 3080 |
| 2923 // Normalize object if needed. | 3081 // Normalize object if needed. |
| 2924 Object* obj; | 3082 Object* obj; |
| 2925 { MaybeObject* maybe_obj = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0); | 3083 { MaybeObject* maybe_obj = NormalizeProperties(CLEAR_INOBJECT_PROPERTIES, 0); |
| (...skipping 225 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3151 switch (GetElementsKind()) { | 3309 switch (GetElementsKind()) { |
| 3152 case FAST_ELEMENTS: | 3310 case FAST_ELEMENTS: |
| 3153 return DeleteFastElement(index); | 3311 return DeleteFastElement(index); |
| 3154 | 3312 |
| 3155 case DICTIONARY_ELEMENTS: | 3313 case DICTIONARY_ELEMENTS: |
| 3156 return DeleteDictionaryElement(index, mode); | 3314 return DeleteDictionaryElement(index, mode); |
| 3157 | 3315 |
| 3158 case FAST_DOUBLE_ELEMENTS: { | 3316 case FAST_DOUBLE_ELEMENTS: { |
| 3159 int length = IsJSArray() | 3317 int length = IsJSArray() |
| 3160 ? Smi::cast(JSArray::cast(this)->length())->value() | 3318 ? Smi::cast(JSArray::cast(this)->length())->value() |
| 3161 : FixedArray::cast(elements())->length(); | 3319 : FixedDoubleArray::cast(elements())->length(); |
| 3162 if (index < static_cast<uint32_t>(length)) { | 3320 if (index < static_cast<uint32_t>(length)) { |
| 3163 FixedDoubleArray::cast(elements())->set_the_hole(index); | 3321 FixedDoubleArray::cast(elements())->set_the_hole(index); |
| 3164 } | 3322 } |
| 3165 break; | 3323 break; |
| 3166 } | 3324 } |
| 3167 case EXTERNAL_PIXEL_ELEMENTS: | 3325 case EXTERNAL_PIXEL_ELEMENTS: |
| 3168 case EXTERNAL_BYTE_ELEMENTS: | 3326 case EXTERNAL_BYTE_ELEMENTS: |
| 3169 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: | 3327 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: |
| 3170 case EXTERNAL_SHORT_ELEMENTS: | 3328 case EXTERNAL_SHORT_ELEMENTS: |
| 3171 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: | 3329 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: |
| (...skipping 23 matching lines...) Expand all Loading... |
| 3195 return DeleteFastElement(index); | 3353 return DeleteFastElement(index); |
| 3196 } | 3354 } |
| 3197 } | 3355 } |
| 3198 break; | 3356 break; |
| 3199 } | 3357 } |
| 3200 } | 3358 } |
| 3201 return isolate->heap()->true_value(); | 3359 return isolate->heap()->true_value(); |
| 3202 } | 3360 } |
| 3203 | 3361 |
| 3204 | 3362 |
| 3363 MaybeObject* JSReceiver::DeleteProperty(String* name, DeleteMode mode) { |
| 3364 if (IsJSProxy()) { |
| 3365 return JSProxy::cast(this)->DeletePropertyWithHandler(name, mode); |
| 3366 } else { |
| 3367 return JSObject::cast(this)->DeleteProperty(name, mode); |
| 3368 } |
| 3369 } |
| 3370 |
| 3371 |
| 3205 MaybeObject* JSObject::DeleteProperty(String* name, DeleteMode mode) { | 3372 MaybeObject* JSObject::DeleteProperty(String* name, DeleteMode mode) { |
| 3206 Isolate* isolate = GetIsolate(); | 3373 Isolate* isolate = GetIsolate(); |
| 3207 // ECMA-262, 3rd, 8.6.2.5 | 3374 // ECMA-262, 3rd, 8.6.2.5 |
| 3208 ASSERT(name->IsString()); | 3375 ASSERT(name->IsString()); |
| 3209 | 3376 |
| 3210 // Check access rights if needed. | 3377 // Check access rights if needed. |
| 3211 if (IsAccessCheckNeeded() && | 3378 if (IsAccessCheckNeeded() && |
| 3212 !isolate->MayNamedAccess(this, name, v8::ACCESS_DELETE)) { | 3379 !isolate->MayNamedAccess(this, name, v8::ACCESS_DELETE)) { |
| 3213 isolate->ReportFailedAccessCheck(this, v8::ACCESS_DELETE); | 3380 isolate->ReportFailedAccessCheck(this, v8::ACCESS_DELETE); |
| 3214 return isolate->heap()->false_value(); | 3381 return isolate->heap()->false_value(); |
| (...skipping 377 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3592 if (!CanSetCallback(name)) { | 3759 if (!CanSetCallback(name)) { |
| 3593 return heap->undefined_value(); | 3760 return heap->undefined_value(); |
| 3594 } | 3761 } |
| 3595 | 3762 |
| 3596 uint32_t index = 0; | 3763 uint32_t index = 0; |
| 3597 bool is_element = name->AsArrayIndex(&index); | 3764 bool is_element = name->AsArrayIndex(&index); |
| 3598 | 3765 |
| 3599 if (is_element) { | 3766 if (is_element) { |
| 3600 switch (GetElementsKind()) { | 3767 switch (GetElementsKind()) { |
| 3601 case FAST_ELEMENTS: | 3768 case FAST_ELEMENTS: |
| 3769 case FAST_DOUBLE_ELEMENTS: |
| 3602 break; | 3770 break; |
| 3603 case EXTERNAL_PIXEL_ELEMENTS: | 3771 case EXTERNAL_PIXEL_ELEMENTS: |
| 3604 case EXTERNAL_BYTE_ELEMENTS: | 3772 case EXTERNAL_BYTE_ELEMENTS: |
| 3605 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: | 3773 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: |
| 3606 case EXTERNAL_SHORT_ELEMENTS: | 3774 case EXTERNAL_SHORT_ELEMENTS: |
| 3607 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: | 3775 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: |
| 3608 case EXTERNAL_INT_ELEMENTS: | 3776 case EXTERNAL_INT_ELEMENTS: |
| 3609 case EXTERNAL_UNSIGNED_INT_ELEMENTS: | 3777 case EXTERNAL_UNSIGNED_INT_ELEMENTS: |
| 3610 case EXTERNAL_FLOAT_ELEMENTS: | 3778 case EXTERNAL_FLOAT_ELEMENTS: |
| 3611 case EXTERNAL_DOUBLE_ELEMENTS: | 3779 case EXTERNAL_DOUBLE_ELEMENTS: |
| 3612 case FAST_DOUBLE_ELEMENTS: | |
| 3613 // Ignore getters and setters on pixel and external array | 3780 // Ignore getters and setters on pixel and external array |
| 3614 // elements. | 3781 // elements. |
| 3615 return heap->undefined_value(); | 3782 return heap->undefined_value(); |
| 3616 case DICTIONARY_ELEMENTS: { | 3783 case DICTIONARY_ELEMENTS: { |
| 3617 Object* probe = | 3784 Object* probe = |
| 3618 FindGetterSetterInDictionary(element_dictionary(), index, heap); | 3785 FindGetterSetterInDictionary(element_dictionary(), index, heap); |
| 3619 if (!probe->IsTheHole()) return probe; | 3786 if (!probe->IsTheHole()) return probe; |
| 3620 // Otherwise allow to override it. | 3787 // Otherwise allow to override it. |
| 3621 break; | 3788 break; |
| 3622 } | 3789 } |
| (...skipping 218 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3841 | 4008 |
| 3842 uint32_t index = 0; | 4009 uint32_t index = 0; |
| 3843 bool is_element = name->AsArrayIndex(&index); | 4010 bool is_element = name->AsArrayIndex(&index); |
| 3844 | 4011 |
| 3845 if (is_element) { | 4012 if (is_element) { |
| 3846 if (IsJSArray()) return isolate->heap()->undefined_value(); | 4013 if (IsJSArray()) return isolate->heap()->undefined_value(); |
| 3847 | 4014 |
| 3848 // Accessors overwrite previous callbacks (cf. with getters/setters). | 4015 // Accessors overwrite previous callbacks (cf. with getters/setters). |
| 3849 switch (GetElementsKind()) { | 4016 switch (GetElementsKind()) { |
| 3850 case FAST_ELEMENTS: | 4017 case FAST_ELEMENTS: |
| 4018 case FAST_DOUBLE_ELEMENTS: |
| 3851 break; | 4019 break; |
| 3852 case EXTERNAL_PIXEL_ELEMENTS: | 4020 case EXTERNAL_PIXEL_ELEMENTS: |
| 3853 case EXTERNAL_BYTE_ELEMENTS: | 4021 case EXTERNAL_BYTE_ELEMENTS: |
| 3854 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: | 4022 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: |
| 3855 case EXTERNAL_SHORT_ELEMENTS: | 4023 case EXTERNAL_SHORT_ELEMENTS: |
| 3856 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: | 4024 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: |
| 3857 case EXTERNAL_INT_ELEMENTS: | 4025 case EXTERNAL_INT_ELEMENTS: |
| 3858 case EXTERNAL_UNSIGNED_INT_ELEMENTS: | 4026 case EXTERNAL_UNSIGNED_INT_ELEMENTS: |
| 3859 case EXTERNAL_FLOAT_ELEMENTS: | 4027 case EXTERNAL_FLOAT_ELEMENTS: |
| 3860 case EXTERNAL_DOUBLE_ELEMENTS: | 4028 case EXTERNAL_DOUBLE_ELEMENTS: |
| 3861 case FAST_DOUBLE_ELEMENTS: | |
| 3862 // Ignore getters and setters on pixel and external array | 4029 // Ignore getters and setters on pixel and external array |
| 3863 // elements. | 4030 // elements. |
| 3864 return isolate->heap()->undefined_value(); | 4031 return isolate->heap()->undefined_value(); |
| 3865 case DICTIONARY_ELEMENTS: | 4032 case DICTIONARY_ELEMENTS: |
| 3866 break; | 4033 break; |
| 3867 case NON_STRICT_ARGUMENTS_ELEMENTS: | 4034 case NON_STRICT_ARGUMENTS_ELEMENTS: |
| 3868 UNIMPLEMENTED(); | 4035 UNIMPLEMENTED(); |
| 3869 break; | 4036 break; |
| 3870 } | 4037 } |
| 3871 | 4038 |
| (...skipping 752 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4624 cache->ElementAdded(); | 4791 cache->ElementAdded(); |
| 4625 return cache; | 4792 return cache; |
| 4626 } | 4793 } |
| 4627 | 4794 |
| 4628 | 4795 |
| 4629 MaybeObject* FixedArray::AddKeysFromJSArray(JSArray* array) { | 4796 MaybeObject* FixedArray::AddKeysFromJSArray(JSArray* array) { |
| 4630 ASSERT(!array->HasExternalArrayElements()); | 4797 ASSERT(!array->HasExternalArrayElements()); |
| 4631 switch (array->GetElementsKind()) { | 4798 switch (array->GetElementsKind()) { |
| 4632 case JSObject::FAST_ELEMENTS: | 4799 case JSObject::FAST_ELEMENTS: |
| 4633 return UnionOfKeys(FixedArray::cast(array->elements())); | 4800 return UnionOfKeys(FixedArray::cast(array->elements())); |
| 4801 case JSObject::FAST_DOUBLE_ELEMENTS: |
| 4802 return UnionOfDoubleKeys(FixedDoubleArray::cast(array->elements())); |
| 4803 break; |
| 4634 case JSObject::DICTIONARY_ELEMENTS: { | 4804 case JSObject::DICTIONARY_ELEMENTS: { |
| 4635 NumberDictionary* dict = array->element_dictionary(); | 4805 NumberDictionary* dict = array->element_dictionary(); |
| 4636 int size = dict->NumberOfElements(); | 4806 int size = dict->NumberOfElements(); |
| 4637 | 4807 |
| 4638 // Allocate a temporary fixed array. | 4808 // Allocate a temporary fixed array. |
| 4639 Object* object; | 4809 Object* object; |
| 4640 { MaybeObject* maybe_object = GetHeap()->AllocateFixedArray(size); | 4810 { MaybeObject* maybe_object = GetHeap()->AllocateFixedArray(size); |
| 4641 if (!maybe_object->ToObject(&object)) return maybe_object; | 4811 if (!maybe_object->ToObject(&object)) return maybe_object; |
| 4642 } | 4812 } |
| 4643 FixedArray* key_array = FixedArray::cast(object); | 4813 FixedArray* key_array = FixedArray::cast(object); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 4658 break; | 4828 break; |
| 4659 case JSObject::EXTERNAL_BYTE_ELEMENTS: | 4829 case JSObject::EXTERNAL_BYTE_ELEMENTS: |
| 4660 case JSObject::EXTERNAL_UNSIGNED_BYTE_ELEMENTS: | 4830 case JSObject::EXTERNAL_UNSIGNED_BYTE_ELEMENTS: |
| 4661 case JSObject::EXTERNAL_SHORT_ELEMENTS: | 4831 case JSObject::EXTERNAL_SHORT_ELEMENTS: |
| 4662 case JSObject::EXTERNAL_UNSIGNED_SHORT_ELEMENTS: | 4832 case JSObject::EXTERNAL_UNSIGNED_SHORT_ELEMENTS: |
| 4663 case JSObject::EXTERNAL_INT_ELEMENTS: | 4833 case JSObject::EXTERNAL_INT_ELEMENTS: |
| 4664 case JSObject::EXTERNAL_UNSIGNED_INT_ELEMENTS: | 4834 case JSObject::EXTERNAL_UNSIGNED_INT_ELEMENTS: |
| 4665 case JSObject::EXTERNAL_FLOAT_ELEMENTS: | 4835 case JSObject::EXTERNAL_FLOAT_ELEMENTS: |
| 4666 case JSObject::EXTERNAL_DOUBLE_ELEMENTS: | 4836 case JSObject::EXTERNAL_DOUBLE_ELEMENTS: |
| 4667 case JSObject::EXTERNAL_PIXEL_ELEMENTS: | 4837 case JSObject::EXTERNAL_PIXEL_ELEMENTS: |
| 4668 case JSObject::FAST_DOUBLE_ELEMENTS: | |
| 4669 break; | 4838 break; |
| 4670 } | 4839 } |
| 4671 UNREACHABLE(); | 4840 UNREACHABLE(); |
| 4672 return GetHeap()->null_value(); // Failure case needs to "return" a value. | 4841 return GetHeap()->null_value(); // Failure case needs to "return" a value. |
| 4673 } | 4842 } |
| 4674 | 4843 |
| 4675 | 4844 |
| 4676 MaybeObject* FixedArray::UnionOfKeys(FixedArray* other) { | 4845 MaybeObject* FixedArray::UnionOfKeys(FixedArray* other) { |
| 4677 int len0 = length(); | 4846 int len0 = length(); |
| 4678 #ifdef DEBUG | 4847 #ifdef DEBUG |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4720 ASSERT(e->IsString() || e->IsNumber()); | 4889 ASSERT(e->IsString() || e->IsNumber()); |
| 4721 result->set(len0 + index, e, mode); | 4890 result->set(len0 + index, e, mode); |
| 4722 index++; | 4891 index++; |
| 4723 } | 4892 } |
| 4724 } | 4893 } |
| 4725 ASSERT(extra == index); | 4894 ASSERT(extra == index); |
| 4726 return result; | 4895 return result; |
| 4727 } | 4896 } |
| 4728 | 4897 |
| 4729 | 4898 |
| 4899 MaybeObject* FixedArray::UnionOfDoubleKeys(FixedDoubleArray* other) { |
| 4900 int len0 = length(); |
| 4901 #ifdef DEBUG |
| 4902 if (FLAG_enable_slow_asserts) { |
| 4903 for (int i = 0; i < len0; i++) { |
| 4904 ASSERT(get(i)->IsString() || get(i)->IsNumber()); |
| 4905 } |
| 4906 } |
| 4907 #endif |
| 4908 int len1 = other->length(); |
| 4909 // Optimize if 'other' is empty. |
| 4910 // We cannot optimize if 'this' is empty, as other may have holes |
| 4911 // or non keys. |
| 4912 if (len1 == 0) return this; |
| 4913 |
| 4914 // Compute how many elements are not in this. |
| 4915 int extra = 0; |
| 4916 Heap* heap = GetHeap(); |
| 4917 Object* obj; |
| 4918 for (int y = 0; y < len1; y++) { |
| 4919 if (!other->is_the_hole(y)) { |
| 4920 MaybeObject* maybe_obj = heap->NumberFromDouble(other->get(y)); |
| 4921 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 4922 if (!HasKey(this, obj)) extra++; |
| 4923 } |
| 4924 } |
| 4925 |
| 4926 if (extra == 0) return this; |
| 4927 |
| 4928 // Allocate the result |
| 4929 { MaybeObject* maybe_obj = GetHeap()->AllocateFixedArray(len0 + extra); |
| 4930 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 4931 } |
| 4932 // Fill in the content |
| 4933 FixedArray* result = FixedArray::cast(obj); |
| 4934 { |
| 4935 // Limit the scope of the AssertNoAllocation |
| 4936 AssertNoAllocation no_gc; |
| 4937 WriteBarrierMode mode = result->GetWriteBarrierMode(no_gc); |
| 4938 for (int i = 0; i < len0; i++) { |
| 4939 Object* e = get(i); |
| 4940 ASSERT(e->IsString() || e->IsNumber()); |
| 4941 result->set(i, e, mode); |
| 4942 } |
| 4943 } |
| 4944 |
| 4945 // Fill in the extra keys. |
| 4946 int index = 0; |
| 4947 for (int y = 0; y < len1; y++) { |
| 4948 if (!other->is_the_hole(y)) { |
| 4949 MaybeObject* maybe_obj = heap->NumberFromDouble(other->get(y)); |
| 4950 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 4951 if (!HasKey(this, obj)) { |
| 4952 result->set(len0 + index, obj); |
| 4953 index++; |
| 4954 } |
| 4955 } |
| 4956 } |
| 4957 ASSERT(extra == index); |
| 4958 return result; |
| 4959 } |
| 4960 |
| 4961 |
| 4730 MaybeObject* FixedArray::CopySize(int new_length) { | 4962 MaybeObject* FixedArray::CopySize(int new_length) { |
| 4731 Heap* heap = GetHeap(); | 4963 Heap* heap = GetHeap(); |
| 4732 if (new_length == 0) return heap->empty_fixed_array(); | 4964 if (new_length == 0) return heap->empty_fixed_array(); |
| 4733 Object* obj; | 4965 Object* obj; |
| 4734 { MaybeObject* maybe_obj = heap->AllocateFixedArray(new_length); | 4966 { MaybeObject* maybe_obj = heap->AllocateFixedArray(new_length); |
| 4735 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 4967 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 4736 } | 4968 } |
| 4737 FixedArray* result = FixedArray::cast(obj); | 4969 FixedArray* result = FixedArray::cast(obj); |
| 4738 // Copy the content | 4970 // Copy the content |
| 4739 AssertNoAllocation no_gc; | 4971 AssertNoAllocation no_gc; |
| (...skipping 2405 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7145 case BUILTIN: return "BUILTIN"; | 7377 case BUILTIN: return "BUILTIN"; |
| 7146 case LOAD_IC: return "LOAD_IC"; | 7378 case LOAD_IC: return "LOAD_IC"; |
| 7147 case KEYED_LOAD_IC: return "KEYED_LOAD_IC"; | 7379 case KEYED_LOAD_IC: return "KEYED_LOAD_IC"; |
| 7148 case STORE_IC: return "STORE_IC"; | 7380 case STORE_IC: return "STORE_IC"; |
| 7149 case KEYED_STORE_IC: return "KEYED_STORE_IC"; | 7381 case KEYED_STORE_IC: return "KEYED_STORE_IC"; |
| 7150 case CALL_IC: return "CALL_IC"; | 7382 case CALL_IC: return "CALL_IC"; |
| 7151 case KEYED_CALL_IC: return "KEYED_CALL_IC"; | 7383 case KEYED_CALL_IC: return "KEYED_CALL_IC"; |
| 7152 case UNARY_OP_IC: return "UNARY_OP_IC"; | 7384 case UNARY_OP_IC: return "UNARY_OP_IC"; |
| 7153 case BINARY_OP_IC: return "BINARY_OP_IC"; | 7385 case BINARY_OP_IC: return "BINARY_OP_IC"; |
| 7154 case COMPARE_IC: return "COMPARE_IC"; | 7386 case COMPARE_IC: return "COMPARE_IC"; |
| 7387 case TO_BOOLEAN_IC: return "TO_BOOLEAN_IC"; |
| 7155 } | 7388 } |
| 7156 UNREACHABLE(); | 7389 UNREACHABLE(); |
| 7157 return NULL; | 7390 return NULL; |
| 7158 } | 7391 } |
| 7159 | 7392 |
| 7160 | 7393 |
| 7161 const char* Code::ICState2String(InlineCacheState state) { | 7394 const char* Code::ICState2String(InlineCacheState state) { |
| 7162 switch (state) { | 7395 switch (state) { |
| 7163 case UNINITIALIZED: return "UNINITIALIZED"; | 7396 case UNINITIALIZED: return "UNINITIALIZED"; |
| 7164 case PREMONOMORPHIC: return "PREMONOMORPHIC"; | 7397 case PREMONOMORPHIC: return "PREMONOMORPHIC"; |
| (...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7335 | 7568 |
| 7336 // Find the new map to use for this object if there is a map change. | 7569 // Find the new map to use for this object if there is a map change. |
| 7337 Map* new_map = NULL; | 7570 Map* new_map = NULL; |
| 7338 if (elements()->map() != heap->non_strict_arguments_elements_map()) { | 7571 if (elements()->map() != heap->non_strict_arguments_elements_map()) { |
| 7339 Object* object; | 7572 Object* object; |
| 7340 MaybeObject* maybe = map()->GetFastElementsMap(); | 7573 MaybeObject* maybe = map()->GetFastElementsMap(); |
| 7341 if (!maybe->ToObject(&object)) return maybe; | 7574 if (!maybe->ToObject(&object)) return maybe; |
| 7342 new_map = Map::cast(object); | 7575 new_map = Map::cast(object); |
| 7343 } | 7576 } |
| 7344 | 7577 |
| 7345 AssertNoAllocation no_gc; | |
| 7346 WriteBarrierMode mode = new_elements->GetWriteBarrierMode(no_gc); | |
| 7347 switch (GetElementsKind()) { | 7578 switch (GetElementsKind()) { |
| 7348 case FAST_ELEMENTS: | 7579 case FAST_ELEMENTS: { |
| 7580 AssertNoAllocation no_gc; |
| 7581 WriteBarrierMode mode = new_elements->GetWriteBarrierMode(no_gc); |
| 7349 CopyFastElementsToFast(FixedArray::cast(elements()), new_elements, mode); | 7582 CopyFastElementsToFast(FixedArray::cast(elements()), new_elements, mode); |
| 7350 set_map(new_map); | 7583 set_map(new_map); |
| 7351 set_elements(new_elements); | 7584 set_elements(new_elements); |
| 7352 break; | 7585 break; |
| 7353 case DICTIONARY_ELEMENTS: | 7586 } |
| 7587 case DICTIONARY_ELEMENTS: { |
| 7588 AssertNoAllocation no_gc; |
| 7589 WriteBarrierMode mode = new_elements->GetWriteBarrierMode(no_gc); |
| 7354 CopySlowElementsToFast(NumberDictionary::cast(elements()), | 7590 CopySlowElementsToFast(NumberDictionary::cast(elements()), |
| 7355 new_elements, | 7591 new_elements, |
| 7356 mode); | 7592 mode); |
| 7357 set_map(new_map); | 7593 set_map(new_map); |
| 7358 set_elements(new_elements); | 7594 set_elements(new_elements); |
| 7359 break; | 7595 break; |
| 7596 } |
| 7360 case NON_STRICT_ARGUMENTS_ELEMENTS: { | 7597 case NON_STRICT_ARGUMENTS_ELEMENTS: { |
| 7598 AssertNoAllocation no_gc; |
| 7599 WriteBarrierMode mode = new_elements->GetWriteBarrierMode(no_gc); |
| 7361 // The object's map and the parameter map are unchanged, the unaliased | 7600 // The object's map and the parameter map are unchanged, the unaliased |
| 7362 // arguments are copied to the new backing store. | 7601 // arguments are copied to the new backing store. |
| 7363 FixedArray* parameter_map = FixedArray::cast(elements()); | 7602 FixedArray* parameter_map = FixedArray::cast(elements()); |
| 7364 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); | 7603 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); |
| 7365 if (arguments->IsDictionary()) { | 7604 if (arguments->IsDictionary()) { |
| 7366 CopySlowElementsToFast(NumberDictionary::cast(arguments), | 7605 CopySlowElementsToFast(NumberDictionary::cast(arguments), |
| 7367 new_elements, | 7606 new_elements, |
| 7368 mode); | 7607 mode); |
| 7369 } else { | 7608 } else { |
| 7370 CopyFastElementsToFast(arguments, new_elements, mode); | 7609 CopyFastElementsToFast(arguments, new_elements, mode); |
| (...skipping 15 matching lines...) Expand all Loading... |
| 7386 MaybeObject* maybe_value_object = | 7625 MaybeObject* maybe_value_object = |
| 7387 GetHeap()->AllocateHeapNumber(old_elements->get(i), TENURED); | 7626 GetHeap()->AllocateHeapNumber(old_elements->get(i), TENURED); |
| 7388 if (!maybe_value_object->ToObject(&obj)) return maybe_value_object; | 7627 if (!maybe_value_object->ToObject(&obj)) return maybe_value_object; |
| 7389 // Force write barrier. It's not worth trying to exploit | 7628 // Force write barrier. It's not worth trying to exploit |
| 7390 // elems->GetWriteBarrierMode(), since it requires an | 7629 // elems->GetWriteBarrierMode(), since it requires an |
| 7391 // AssertNoAllocation stack object that would have to be positioned | 7630 // AssertNoAllocation stack object that would have to be positioned |
| 7392 // after the HeapNumber allocation anyway. | 7631 // after the HeapNumber allocation anyway. |
| 7393 new_elements->set(i, obj, UPDATE_WRITE_BARRIER); | 7632 new_elements->set(i, obj, UPDATE_WRITE_BARRIER); |
| 7394 } | 7633 } |
| 7395 } | 7634 } |
| 7635 set_map(new_map); |
| 7636 set_elements(new_elements); |
| 7396 break; | 7637 break; |
| 7397 } | 7638 } |
| 7398 case EXTERNAL_BYTE_ELEMENTS: | 7639 case EXTERNAL_BYTE_ELEMENTS: |
| 7399 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: | 7640 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: |
| 7400 case EXTERNAL_SHORT_ELEMENTS: | 7641 case EXTERNAL_SHORT_ELEMENTS: |
| 7401 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: | 7642 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: |
| 7402 case EXTERNAL_INT_ELEMENTS: | 7643 case EXTERNAL_INT_ELEMENTS: |
| 7403 case EXTERNAL_UNSIGNED_INT_ELEMENTS: | 7644 case EXTERNAL_UNSIGNED_INT_ELEMENTS: |
| 7404 case EXTERNAL_FLOAT_ELEMENTS: | 7645 case EXTERNAL_FLOAT_ELEMENTS: |
| 7405 case EXTERNAL_DOUBLE_ELEMENTS: | 7646 case EXTERNAL_DOUBLE_ELEMENTS: |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7448 } | 7689 } |
| 7449 case DICTIONARY_ELEMENTS: { | 7690 case DICTIONARY_ELEMENTS: { |
| 7450 elems->Initialize(NumberDictionary::cast(elements())); | 7691 elems->Initialize(NumberDictionary::cast(elements())); |
| 7451 break; | 7692 break; |
| 7452 } | 7693 } |
| 7453 default: | 7694 default: |
| 7454 UNREACHABLE(); | 7695 UNREACHABLE(); |
| 7455 break; | 7696 break; |
| 7456 } | 7697 } |
| 7457 | 7698 |
| 7699 ASSERT(new_map->has_fast_double_elements()); |
| 7458 set_map(new_map); | 7700 set_map(new_map); |
| 7701 ASSERT(elems->IsFixedDoubleArray()); |
| 7459 set_elements(elems); | 7702 set_elements(elems); |
| 7460 | 7703 |
| 7461 if (IsJSArray()) { | 7704 if (IsJSArray()) { |
| 7462 JSArray::cast(this)->set_length(Smi::FromInt(length)); | 7705 JSArray::cast(this)->set_length(Smi::FromInt(length)); |
| 7463 } | 7706 } |
| 7464 | 7707 |
| 7465 return this; | 7708 return this; |
| 7466 } | 7709 } |
| 7467 | 7710 |
| 7468 | 7711 |
| 7469 MaybeObject* JSObject::SetSlowElements(Object* len) { | 7712 MaybeObject* JSObject::SetSlowElements(Object* len) { |
| 7470 // We should never end in here with a pixel or external array. | 7713 // We should never end in here with a pixel or external array. |
| 7471 ASSERT(!HasExternalArrayElements()); | 7714 ASSERT(!HasExternalArrayElements()); |
| 7472 | 7715 |
| 7473 uint32_t new_length = static_cast<uint32_t>(len->Number()); | 7716 uint32_t new_length = static_cast<uint32_t>(len->Number()); |
| 7474 | 7717 |
| 7475 switch (GetElementsKind()) { | 7718 switch (GetElementsKind()) { |
| 7476 case FAST_ELEMENTS: { | 7719 case FAST_ELEMENTS: { |
| 7720 case FAST_DOUBLE_ELEMENTS: |
| 7477 // Make sure we never try to shrink dense arrays into sparse arrays. | 7721 // Make sure we never try to shrink dense arrays into sparse arrays. |
| 7478 ASSERT(static_cast<uint32_t>(FixedArray::cast(elements())->length()) <= | 7722 ASSERT(static_cast<uint32_t>( |
| 7479 new_length); | 7723 FixedArrayBase::cast(elements())->length()) <= new_length); |
| 7480 MaybeObject* result = NormalizeElements(); | 7724 MaybeObject* result = NormalizeElements(); |
| 7481 if (result->IsFailure()) return result; | 7725 if (result->IsFailure()) return result; |
| 7482 | 7726 |
| 7483 // Update length for JSArrays. | 7727 // Update length for JSArrays. |
| 7484 if (IsJSArray()) JSArray::cast(this)->set_length(len); | 7728 if (IsJSArray()) JSArray::cast(this)->set_length(len); |
| 7485 break; | 7729 break; |
| 7486 } | 7730 } |
| 7487 case DICTIONARY_ELEMENTS: { | 7731 case DICTIONARY_ELEMENTS: { |
| 7488 if (IsJSArray()) { | 7732 if (IsJSArray()) { |
| 7489 uint32_t old_length = | 7733 uint32_t old_length = |
| 7490 static_cast<uint32_t>(JSArray::cast(this)->length()->Number()); | 7734 static_cast<uint32_t>(JSArray::cast(this)->length()->Number()); |
| 7491 element_dictionary()->RemoveNumberEntries(new_length, old_length), | 7735 element_dictionary()->RemoveNumberEntries(new_length, old_length), |
| 7492 JSArray::cast(this)->set_length(len); | 7736 JSArray::cast(this)->set_length(len); |
| 7493 } | 7737 } |
| 7494 break; | 7738 break; |
| 7495 } | 7739 } |
| 7496 case NON_STRICT_ARGUMENTS_ELEMENTS: | 7740 case NON_STRICT_ARGUMENTS_ELEMENTS: |
| 7497 UNIMPLEMENTED(); | 7741 UNIMPLEMENTED(); |
| 7498 break; | 7742 break; |
| 7499 case EXTERNAL_BYTE_ELEMENTS: | 7743 case EXTERNAL_BYTE_ELEMENTS: |
| 7500 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: | 7744 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: |
| 7501 case EXTERNAL_SHORT_ELEMENTS: | 7745 case EXTERNAL_SHORT_ELEMENTS: |
| 7502 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: | 7746 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: |
| 7503 case EXTERNAL_INT_ELEMENTS: | 7747 case EXTERNAL_INT_ELEMENTS: |
| 7504 case EXTERNAL_UNSIGNED_INT_ELEMENTS: | 7748 case EXTERNAL_UNSIGNED_INT_ELEMENTS: |
| 7505 case EXTERNAL_FLOAT_ELEMENTS: | 7749 case EXTERNAL_FLOAT_ELEMENTS: |
| 7506 case EXTERNAL_DOUBLE_ELEMENTS: | 7750 case EXTERNAL_DOUBLE_ELEMENTS: |
| 7507 case EXTERNAL_PIXEL_ELEMENTS: | 7751 case EXTERNAL_PIXEL_ELEMENTS: |
| 7508 case FAST_DOUBLE_ELEMENTS: | |
| 7509 UNREACHABLE(); | 7752 UNREACHABLE(); |
| 7510 break; | 7753 break; |
| 7511 } | 7754 } |
| 7512 return this; | 7755 return this; |
| 7513 } | 7756 } |
| 7514 | 7757 |
| 7515 | 7758 |
| 7516 MaybeObject* JSArray::Initialize(int capacity) { | 7759 MaybeObject* JSArray::Initialize(int capacity) { |
| 7517 Heap* heap = GetHeap(); | 7760 Heap* heap = GetHeap(); |
| 7518 ASSERT(capacity >= 0); | 7761 ASSERT(capacity >= 0); |
| (...skipping 19 matching lines...) Expand all Loading... |
| 7538 int old_size = old_backing->length(); | 7781 int old_size = old_backing->length(); |
| 7539 int new_size = required_size > old_size ? required_size : old_size; | 7782 int new_size = required_size > old_size ? required_size : old_size; |
| 7540 Handle<FixedArray> new_backing = FACTORY->NewFixedArray(new_size); | 7783 Handle<FixedArray> new_backing = FACTORY->NewFixedArray(new_size); |
| 7541 // Can't use this any more now because we may have had a GC! | 7784 // Can't use this any more now because we may have had a GC! |
| 7542 for (int i = 0; i < old_size; i++) new_backing->set(i, old_backing->get(i)); | 7785 for (int i = 0; i < old_size; i++) new_backing->set(i, old_backing->get(i)); |
| 7543 self->SetContent(*new_backing); | 7786 self->SetContent(*new_backing); |
| 7544 } | 7787 } |
| 7545 | 7788 |
| 7546 | 7789 |
| 7547 static Failure* ArrayLengthRangeError(Heap* heap) { | 7790 static Failure* ArrayLengthRangeError(Heap* heap) { |
| 7548 HandleScope scope; | 7791 HandleScope scope(heap->isolate()); |
| 7549 return heap->isolate()->Throw( | 7792 return heap->isolate()->Throw( |
| 7550 *FACTORY->NewRangeError("invalid_array_length", | 7793 *FACTORY->NewRangeError("invalid_array_length", |
| 7551 HandleVector<Object>(NULL, 0))); | 7794 HandleVector<Object>(NULL, 0))); |
| 7552 } | 7795 } |
| 7553 | 7796 |
| 7554 | 7797 |
| 7555 MaybeObject* JSObject::SetElementsLength(Object* len) { | 7798 MaybeObject* JSObject::SetElementsLength(Object* len) { |
| 7556 // We should never end in here with a pixel or external array. | 7799 // We should never end in here with a pixel or external array. |
| 7557 ASSERT(AllowsSetElementsLength()); | 7800 ASSERT(AllowsSetElementsLength()); |
| 7558 | 7801 |
| 7559 MaybeObject* maybe_smi_length = len->ToSmi(); | 7802 MaybeObject* maybe_smi_length = len->ToSmi(); |
| 7560 Object* smi_length = Smi::FromInt(0); | 7803 Object* smi_length = Smi::FromInt(0); |
| 7561 if (maybe_smi_length->ToObject(&smi_length) && smi_length->IsSmi()) { | 7804 if (maybe_smi_length->ToObject(&smi_length) && smi_length->IsSmi()) { |
| 7562 const int value = Smi::cast(smi_length)->value(); | 7805 const int value = Smi::cast(smi_length)->value(); |
| 7563 if (value < 0) return ArrayLengthRangeError(GetHeap()); | 7806 if (value < 0) return ArrayLengthRangeError(GetHeap()); |
| 7564 switch (GetElementsKind()) { | 7807 JSObject::ElementsKind elements_kind = GetElementsKind(); |
| 7565 case FAST_ELEMENTS: { | 7808 switch (elements_kind) { |
| 7566 int old_capacity = FixedArray::cast(elements())->length(); | 7809 case FAST_ELEMENTS: |
| 7810 case FAST_DOUBLE_ELEMENTS: { |
| 7811 int old_capacity = FixedArrayBase::cast(elements())->length(); |
| 7567 if (value <= old_capacity) { | 7812 if (value <= old_capacity) { |
| 7568 if (IsJSArray()) { | 7813 if (IsJSArray()) { |
| 7569 Object* obj; | 7814 Object* obj; |
| 7570 { MaybeObject* maybe_obj = EnsureWritableFastElements(); | 7815 if (elements_kind == FAST_ELEMENTS) { |
| 7816 MaybeObject* maybe_obj = EnsureWritableFastElements(); |
| 7571 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 7817 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 7572 } | 7818 } |
| 7573 FixedArray* fast_elements = FixedArray::cast(elements()); | |
| 7574 if (2 * value <= old_capacity) { | 7819 if (2 * value <= old_capacity) { |
| 7575 // If more than half the elements won't be used, trim the array. | 7820 // If more than half the elements won't be used, trim the array. |
| 7576 if (value == 0) { | 7821 if (value == 0) { |
| 7577 initialize_elements(); | 7822 initialize_elements(); |
| 7578 } else { | 7823 } else { |
| 7579 fast_elements->set_length(value); | 7824 Address filler_start; |
| 7580 Address filler_start = fast_elements->address() + | 7825 int filler_size; |
| 7581 FixedArray::OffsetOfElementAt(value); | 7826 if (GetElementsKind() == FAST_ELEMENTS) { |
| 7582 int filler_size = (old_capacity - value) * kPointerSize; | 7827 FixedArray* fast_elements = FixedArray::cast(elements()); |
| 7828 fast_elements->set_length(value); |
| 7829 filler_start = fast_elements->address() + |
| 7830 FixedArray::OffsetOfElementAt(value); |
| 7831 filler_size = (old_capacity - value) * kPointerSize; |
| 7832 } else { |
| 7833 ASSERT(GetElementsKind() == FAST_DOUBLE_ELEMENTS); |
| 7834 FixedDoubleArray* fast_double_elements = |
| 7835 FixedDoubleArray::cast(elements()); |
| 7836 fast_double_elements->set_length(value); |
| 7837 filler_start = fast_double_elements->address() + |
| 7838 FixedDoubleArray::OffsetOfElementAt(value); |
| 7839 filler_size = (old_capacity - value) * kDoubleSize; |
| 7840 } |
| 7583 GetHeap()->CreateFillerObjectAt(filler_start, filler_size); | 7841 GetHeap()->CreateFillerObjectAt(filler_start, filler_size); |
| 7584 } | 7842 } |
| 7585 } else { | 7843 } else { |
| 7586 // Otherwise, fill the unused tail with holes. | 7844 // Otherwise, fill the unused tail with holes. |
| 7587 int old_length = FastD2I(JSArray::cast(this)->length()->Number()); | 7845 int old_length = FastD2I(JSArray::cast(this)->length()->Number()); |
| 7588 for (int i = value; i < old_length; i++) { | 7846 if (GetElementsKind() == FAST_ELEMENTS) { |
| 7589 fast_elements->set_the_hole(i); | 7847 FixedArray* fast_elements = FixedArray::cast(elements()); |
| 7848 for (int i = value; i < old_length; i++) { |
| 7849 fast_elements->set_the_hole(i); |
| 7850 } |
| 7851 } else { |
| 7852 ASSERT(GetElementsKind() == FAST_DOUBLE_ELEMENTS); |
| 7853 FixedDoubleArray* fast_double_elements = |
| 7854 FixedDoubleArray::cast(elements()); |
| 7855 for (int i = value; i < old_length; i++) { |
| 7856 fast_double_elements->set_the_hole(i); |
| 7857 } |
| 7590 } | 7858 } |
| 7591 } | 7859 } |
| 7592 JSArray::cast(this)->set_length(Smi::cast(smi_length)); | 7860 JSArray::cast(this)->set_length(Smi::cast(smi_length)); |
| 7593 } | 7861 } |
| 7594 return this; | 7862 return this; |
| 7595 } | 7863 } |
| 7596 int min = NewElementsCapacity(old_capacity); | 7864 int min = NewElementsCapacity(old_capacity); |
| 7597 int new_capacity = value > min ? value : min; | 7865 int new_capacity = value > min ? value : min; |
| 7598 if (new_capacity <= kMaxFastElementsLength || | 7866 if (!ShouldConvertToSlowElements(new_capacity)) { |
| 7599 !ShouldConvertToSlowElements(new_capacity)) { | 7867 MaybeObject* result; |
| 7600 MaybeObject* result = | 7868 if (GetElementsKind() == FAST_ELEMENTS) { |
| 7601 SetFastElementsCapacityAndLength(new_capacity, value); | 7869 result = SetFastElementsCapacityAndLength(new_capacity, value); |
| 7870 } else { |
| 7871 ASSERT(GetElementsKind() == FAST_DOUBLE_ELEMENTS); |
| 7872 result = SetFastDoubleElementsCapacityAndLength(new_capacity, |
| 7873 value); |
| 7874 } |
| 7602 if (result->IsFailure()) return result; | 7875 if (result->IsFailure()) return result; |
| 7603 return this; | 7876 return this; |
| 7604 } | 7877 } |
| 7605 break; | 7878 break; |
| 7606 } | 7879 } |
| 7607 case DICTIONARY_ELEMENTS: { | 7880 case DICTIONARY_ELEMENTS: { |
| 7608 if (IsJSArray()) { | 7881 if (IsJSArray()) { |
| 7609 if (value == 0) { | 7882 if (value == 0) { |
| 7610 // If the length of a slow array is reset to zero, we clear | 7883 // If the length of a slow array is reset to zero, we clear |
| 7611 // the array and flush backing storage. This has the added | 7884 // the array and flush backing storage. This has the added |
| (...skipping 15 matching lines...) Expand all Loading... |
| 7627 case NON_STRICT_ARGUMENTS_ELEMENTS: | 7900 case NON_STRICT_ARGUMENTS_ELEMENTS: |
| 7628 case EXTERNAL_BYTE_ELEMENTS: | 7901 case EXTERNAL_BYTE_ELEMENTS: |
| 7629 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: | 7902 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: |
| 7630 case EXTERNAL_SHORT_ELEMENTS: | 7903 case EXTERNAL_SHORT_ELEMENTS: |
| 7631 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: | 7904 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: |
| 7632 case EXTERNAL_INT_ELEMENTS: | 7905 case EXTERNAL_INT_ELEMENTS: |
| 7633 case EXTERNAL_UNSIGNED_INT_ELEMENTS: | 7906 case EXTERNAL_UNSIGNED_INT_ELEMENTS: |
| 7634 case EXTERNAL_FLOAT_ELEMENTS: | 7907 case EXTERNAL_FLOAT_ELEMENTS: |
| 7635 case EXTERNAL_DOUBLE_ELEMENTS: | 7908 case EXTERNAL_DOUBLE_ELEMENTS: |
| 7636 case EXTERNAL_PIXEL_ELEMENTS: | 7909 case EXTERNAL_PIXEL_ELEMENTS: |
| 7637 case FAST_DOUBLE_ELEMENTS: | |
| 7638 UNREACHABLE(); | 7910 UNREACHABLE(); |
| 7639 break; | 7911 break; |
| 7640 } | 7912 } |
| 7641 } | 7913 } |
| 7642 | 7914 |
| 7643 // General slow case. | 7915 // General slow case. |
| 7644 if (len->IsNumber()) { | 7916 if (len->IsNumber()) { |
| 7645 uint32_t length; | 7917 uint32_t length; |
| 7646 if (len->ToArrayIndex(&length)) { | 7918 if (len->ToArrayIndex(&length)) { |
| 7647 return SetSlowElements(len); | 7919 return SetSlowElements(len); |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7736 | 8008 |
| 7737 // From 8.6.2 Object Internal Methods | 8009 // From 8.6.2 Object Internal Methods |
| 7738 // ... | 8010 // ... |
| 7739 // In addition, if [[Extensible]] is false the value of the [[Class]] and | 8011 // In addition, if [[Extensible]] is false the value of the [[Class]] and |
| 7740 // [[Prototype]] internal properties of the object may not be modified. | 8012 // [[Prototype]] internal properties of the object may not be modified. |
| 7741 // ... | 8013 // ... |
| 7742 // Implementation specific extensions that modify [[Class]], [[Prototype]] | 8014 // Implementation specific extensions that modify [[Class]], [[Prototype]] |
| 7743 // or [[Extensible]] must not violate the invariants defined in the preceding | 8015 // or [[Extensible]] must not violate the invariants defined in the preceding |
| 7744 // paragraph. | 8016 // paragraph. |
| 7745 if (!this->map()->is_extensible()) { | 8017 if (!this->map()->is_extensible()) { |
| 7746 HandleScope scope; | 8018 HandleScope scope(heap->isolate()); |
| 7747 Handle<Object> handle(this, heap->isolate()); | 8019 Handle<Object> handle(this, heap->isolate()); |
| 7748 return heap->isolate()->Throw( | 8020 return heap->isolate()->Throw( |
| 7749 *FACTORY->NewTypeError("non_extensible_proto", | 8021 *FACTORY->NewTypeError("non_extensible_proto", |
| 7750 HandleVector<Object>(&handle, 1))); | 8022 HandleVector<Object>(&handle, 1))); |
| 7751 } | 8023 } |
| 7752 | 8024 |
| 7753 // Before we can set the prototype we need to be sure | 8025 // Before we can set the prototype we need to be sure |
| 7754 // prototype cycles are prevented. | 8026 // prototype cycles are prevented. |
| 7755 // It is sufficient to validate that the receiver is not in the new prototype | 8027 // It is sufficient to validate that the receiver is not in the new prototype |
| 7756 // chain. | 8028 // chain. |
| 7757 for (Object* pt = value; pt != heap->null_value(); pt = pt->GetPrototype()) { | 8029 for (Object* pt = value; pt != heap->null_value(); pt = pt->GetPrototype()) { |
| 7758 if (JSObject::cast(pt) == this) { | 8030 if (JSObject::cast(pt) == this) { |
| 7759 // Cycle detected. | 8031 // Cycle detected. |
| 7760 HandleScope scope; | 8032 HandleScope scope(heap->isolate()); |
| 7761 return heap->isolate()->Throw( | 8033 return heap->isolate()->Throw( |
| 7762 *FACTORY->NewError("cyclic_proto", HandleVector<Object>(NULL, 0))); | 8034 *FACTORY->NewError("cyclic_proto", HandleVector<Object>(NULL, 0))); |
| 7763 } | 8035 } |
| 7764 } | 8036 } |
| 7765 | 8037 |
| 7766 JSReceiver* real_receiver = this; | 8038 JSReceiver* real_receiver = this; |
| 7767 | 8039 |
| 7768 if (skip_hidden_prototypes) { | 8040 if (skip_hidden_prototypes) { |
| 7769 // Find the first object in the chain whose prototype object is not | 8041 // Find the first object in the chain whose prototype object is not |
| 7770 // hidden and set the new prototype on that object. | 8042 // hidden and set the new prototype on that object. |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7810 uint32_t length = IsJSArray() ? | 8082 uint32_t length = IsJSArray() ? |
| 7811 static_cast<uint32_t> | 8083 static_cast<uint32_t> |
| 7812 (Smi::cast(JSArray::cast(this)->length())->value()) : | 8084 (Smi::cast(JSArray::cast(this)->length())->value()) : |
| 7813 static_cast<uint32_t>(FixedArray::cast(elements())->length()); | 8085 static_cast<uint32_t>(FixedArray::cast(elements())->length()); |
| 7814 if ((index < length) && | 8086 if ((index < length) && |
| 7815 !FixedArray::cast(elements())->get(index)->IsTheHole()) { | 8087 !FixedArray::cast(elements())->get(index)->IsTheHole()) { |
| 7816 return true; | 8088 return true; |
| 7817 } | 8089 } |
| 7818 break; | 8090 break; |
| 7819 } | 8091 } |
| 8092 case FAST_DOUBLE_ELEMENTS: { |
| 8093 uint32_t length = IsJSArray() ? |
| 8094 static_cast<uint32_t> |
| 8095 (Smi::cast(JSArray::cast(this)->length())->value()) : |
| 8096 static_cast<uint32_t>(FixedDoubleArray::cast(elements())->length()); |
| 8097 if ((index < length) && |
| 8098 !FixedDoubleArray::cast(elements())->is_the_hole(index)) { |
| 8099 return true; |
| 8100 } |
| 8101 break; |
| 8102 } |
| 7820 case EXTERNAL_PIXEL_ELEMENTS: { | 8103 case EXTERNAL_PIXEL_ELEMENTS: { |
| 7821 ExternalPixelArray* pixels = ExternalPixelArray::cast(elements()); | 8104 ExternalPixelArray* pixels = ExternalPixelArray::cast(elements()); |
| 7822 if (index < static_cast<uint32_t>(pixels->length())) { | 8105 if (index < static_cast<uint32_t>(pixels->length())) { |
| 7823 return true; | 8106 return true; |
| 7824 } | 8107 } |
| 7825 break; | 8108 break; |
| 7826 } | 8109 } |
| 7827 case EXTERNAL_BYTE_ELEMENTS: | 8110 case EXTERNAL_BYTE_ELEMENTS: |
| 7828 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: | 8111 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: |
| 7829 case EXTERNAL_SHORT_ELEMENTS: | 8112 case EXTERNAL_SHORT_ELEMENTS: |
| 7830 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: | 8113 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: |
| 7831 case EXTERNAL_INT_ELEMENTS: | 8114 case EXTERNAL_INT_ELEMENTS: |
| 7832 case EXTERNAL_UNSIGNED_INT_ELEMENTS: | 8115 case EXTERNAL_UNSIGNED_INT_ELEMENTS: |
| 7833 case EXTERNAL_FLOAT_ELEMENTS: | 8116 case EXTERNAL_FLOAT_ELEMENTS: |
| 7834 case EXTERNAL_DOUBLE_ELEMENTS: | 8117 case EXTERNAL_DOUBLE_ELEMENTS: { |
| 7835 case FAST_DOUBLE_ELEMENTS: { | |
| 7836 ExternalArray* array = ExternalArray::cast(elements()); | 8118 ExternalArray* array = ExternalArray::cast(elements()); |
| 7837 if (index < static_cast<uint32_t>(array->length())) { | 8119 if (index < static_cast<uint32_t>(array->length())) { |
| 7838 return true; | 8120 return true; |
| 7839 } | 8121 } |
| 7840 break; | 8122 break; |
| 7841 } | 8123 } |
| 7842 case DICTIONARY_ELEMENTS: { | 8124 case DICTIONARY_ELEMENTS: { |
| 7843 if (element_dictionary()->FindEntry(index) | 8125 if (element_dictionary()->FindEntry(index) |
| 7844 != NumberDictionary::kNotFound) { | 8126 != NumberDictionary::kNotFound) { |
| 7845 return true; | 8127 return true; |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7936 uint32_t length = IsJSArray() ? | 8218 uint32_t length = IsJSArray() ? |
| 7937 static_cast<uint32_t> | 8219 static_cast<uint32_t> |
| 7938 (Smi::cast(JSArray::cast(this)->length())->value()) : | 8220 (Smi::cast(JSArray::cast(this)->length())->value()) : |
| 7939 static_cast<uint32_t>(FixedArray::cast(elements())->length()); | 8221 static_cast<uint32_t>(FixedArray::cast(elements())->length()); |
| 7940 if ((index < length) && | 8222 if ((index < length) && |
| 7941 !FixedArray::cast(elements())->get(index)->IsTheHole()) { | 8223 !FixedArray::cast(elements())->get(index)->IsTheHole()) { |
| 7942 return FAST_ELEMENT; | 8224 return FAST_ELEMENT; |
| 7943 } | 8225 } |
| 7944 break; | 8226 break; |
| 7945 } | 8227 } |
| 8228 case FAST_DOUBLE_ELEMENTS: { |
| 8229 uint32_t length = IsJSArray() ? |
| 8230 static_cast<uint32_t> |
| 8231 (Smi::cast(JSArray::cast(this)->length())->value()) : |
| 8232 static_cast<uint32_t>(FixedDoubleArray::cast(elements())->length()); |
| 8233 if ((index < length) && |
| 8234 !FixedDoubleArray::cast(elements())->is_the_hole(index)) { |
| 8235 return FAST_ELEMENT; |
| 8236 } |
| 8237 break; |
| 8238 } |
| 7946 case EXTERNAL_PIXEL_ELEMENTS: { | 8239 case EXTERNAL_PIXEL_ELEMENTS: { |
| 7947 ExternalPixelArray* pixels = ExternalPixelArray::cast(elements()); | 8240 ExternalPixelArray* pixels = ExternalPixelArray::cast(elements()); |
| 7948 if (index < static_cast<uint32_t>(pixels->length())) return FAST_ELEMENT; | 8241 if (index < static_cast<uint32_t>(pixels->length())) return FAST_ELEMENT; |
| 7949 break; | 8242 break; |
| 7950 } | 8243 } |
| 7951 case EXTERNAL_BYTE_ELEMENTS: | 8244 case EXTERNAL_BYTE_ELEMENTS: |
| 7952 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: | 8245 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: |
| 7953 case EXTERNAL_SHORT_ELEMENTS: | 8246 case EXTERNAL_SHORT_ELEMENTS: |
| 7954 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: | 8247 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: |
| 7955 case EXTERNAL_INT_ELEMENTS: | 8248 case EXTERNAL_INT_ELEMENTS: |
| 7956 case EXTERNAL_UNSIGNED_INT_ELEMENTS: | 8249 case EXTERNAL_UNSIGNED_INT_ELEMENTS: |
| 7957 case EXTERNAL_FLOAT_ELEMENTS: | 8250 case EXTERNAL_FLOAT_ELEMENTS: |
| 7958 case EXTERNAL_DOUBLE_ELEMENTS: { | 8251 case EXTERNAL_DOUBLE_ELEMENTS: { |
| 7959 ExternalArray* array = ExternalArray::cast(elements()); | 8252 ExternalArray* array = ExternalArray::cast(elements()); |
| 7960 if (index < static_cast<uint32_t>(array->length())) return FAST_ELEMENT; | 8253 if (index < static_cast<uint32_t>(array->length())) return FAST_ELEMENT; |
| 7961 break; | 8254 break; |
| 7962 } | 8255 } |
| 7963 case FAST_DOUBLE_ELEMENTS: | |
| 7964 UNREACHABLE(); | |
| 7965 break; | |
| 7966 case DICTIONARY_ELEMENTS: { | 8256 case DICTIONARY_ELEMENTS: { |
| 7967 if (element_dictionary()->FindEntry(index) != | 8257 if (element_dictionary()->FindEntry(index) != |
| 7968 NumberDictionary::kNotFound) { | 8258 NumberDictionary::kNotFound) { |
| 7969 return DICTIONARY_ELEMENT; | 8259 return DICTIONARY_ELEMENT; |
| 7970 } | 8260 } |
| 7971 break; | 8261 break; |
| 7972 } | 8262 } |
| 7973 case NON_STRICT_ARGUMENTS_ELEMENTS: { | 8263 case NON_STRICT_ARGUMENTS_ELEMENTS: { |
| 7974 // Aliased parameters and non-aliased elements in a fast backing store | 8264 // Aliased parameters and non-aliased elements in a fast backing store |
| 7975 // behave as FAST_ELEMENT. Non-aliased elements in a dictionary | 8265 // behave as FAST_ELEMENT. Non-aliased elements in a dictionary |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8040 switch (kind) { | 8330 switch (kind) { |
| 8041 case FAST_ELEMENTS: { | 8331 case FAST_ELEMENTS: { |
| 8042 uint32_t length = IsJSArray() ? | 8332 uint32_t length = IsJSArray() ? |
| 8043 static_cast<uint32_t> | 8333 static_cast<uint32_t> |
| 8044 (Smi::cast(JSArray::cast(this)->length())->value()) : | 8334 (Smi::cast(JSArray::cast(this)->length())->value()) : |
| 8045 static_cast<uint32_t>(FixedArray::cast(elements())->length()); | 8335 static_cast<uint32_t>(FixedArray::cast(elements())->length()); |
| 8046 if ((index < length) && | 8336 if ((index < length) && |
| 8047 !FixedArray::cast(elements())->get(index)->IsTheHole()) return true; | 8337 !FixedArray::cast(elements())->get(index)->IsTheHole()) return true; |
| 8048 break; | 8338 break; |
| 8049 } | 8339 } |
| 8340 case FAST_DOUBLE_ELEMENTS: { |
| 8341 uint32_t length = IsJSArray() ? |
| 8342 static_cast<uint32_t> |
| 8343 (Smi::cast(JSArray::cast(this)->length())->value()) : |
| 8344 static_cast<uint32_t>(FixedDoubleArray::cast(elements())->length()); |
| 8345 if ((index < length) && |
| 8346 !FixedDoubleArray::cast(elements())->is_the_hole(index)) return true; |
| 8347 break; |
| 8348 } |
| 8050 case EXTERNAL_PIXEL_ELEMENTS: { | 8349 case EXTERNAL_PIXEL_ELEMENTS: { |
| 8051 ExternalPixelArray* pixels = ExternalPixelArray::cast(elements()); | 8350 ExternalPixelArray* pixels = ExternalPixelArray::cast(elements()); |
| 8052 if (index < static_cast<uint32_t>(pixels->length())) { | 8351 if (index < static_cast<uint32_t>(pixels->length())) { |
| 8053 return true; | 8352 return true; |
| 8054 } | 8353 } |
| 8055 break; | 8354 break; |
| 8056 } | 8355 } |
| 8057 case EXTERNAL_BYTE_ELEMENTS: | 8356 case EXTERNAL_BYTE_ELEMENTS: |
| 8058 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: | 8357 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: |
| 8059 case EXTERNAL_SHORT_ELEMENTS: | 8358 case EXTERNAL_SHORT_ELEMENTS: |
| 8060 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: | 8359 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: |
| 8061 case EXTERNAL_INT_ELEMENTS: | 8360 case EXTERNAL_INT_ELEMENTS: |
| 8062 case EXTERNAL_UNSIGNED_INT_ELEMENTS: | 8361 case EXTERNAL_UNSIGNED_INT_ELEMENTS: |
| 8063 case EXTERNAL_FLOAT_ELEMENTS: | 8362 case EXTERNAL_FLOAT_ELEMENTS: |
| 8064 case EXTERNAL_DOUBLE_ELEMENTS: { | 8363 case EXTERNAL_DOUBLE_ELEMENTS: { |
| 8065 ExternalArray* array = ExternalArray::cast(elements()); | 8364 ExternalArray* array = ExternalArray::cast(elements()); |
| 8066 if (index < static_cast<uint32_t>(array->length())) { | 8365 if (index < static_cast<uint32_t>(array->length())) { |
| 8067 return true; | 8366 return true; |
| 8068 } | 8367 } |
| 8069 break; | 8368 break; |
| 8070 } | 8369 } |
| 8071 case FAST_DOUBLE_ELEMENTS: | |
| 8072 UNREACHABLE(); | |
| 8073 break; | |
| 8074 case DICTIONARY_ELEMENTS: { | 8370 case DICTIONARY_ELEMENTS: { |
| 8075 if (element_dictionary()->FindEntry(index) | 8371 if (element_dictionary()->FindEntry(index) |
| 8076 != NumberDictionary::kNotFound) { | 8372 != NumberDictionary::kNotFound) { |
| 8077 return true; | 8373 return true; |
| 8078 } | 8374 } |
| 8079 break; | 8375 break; |
| 8080 } | 8376 } |
| 8081 case NON_STRICT_ARGUMENTS_ELEMENTS: { | 8377 case NON_STRICT_ARGUMENTS_ELEMENTS: { |
| 8082 FixedArray* parameter_map = FixedArray::cast(elements()); | 8378 FixedArray* parameter_map = FixedArray::cast(elements()); |
| 8083 uint32_t length = parameter_map->length(); | 8379 uint32_t length = parameter_map->length(); |
| (...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8316 JSArray::cast(this)->set_length(Smi::FromInt(index + 1)); | 8612 JSArray::cast(this)->set_length(Smi::FromInt(index + 1)); |
| 8317 } | 8613 } |
| 8318 } | 8614 } |
| 8319 return value; | 8615 return value; |
| 8320 } | 8616 } |
| 8321 | 8617 |
| 8322 // Allow gap in fast case. | 8618 // Allow gap in fast case. |
| 8323 if ((index - length) < kMaxGap) { | 8619 if ((index - length) < kMaxGap) { |
| 8324 // Try allocating extra space. | 8620 // Try allocating extra space. |
| 8325 int new_capacity = NewElementsCapacity(index + 1); | 8621 int new_capacity = NewElementsCapacity(index + 1); |
| 8326 if (new_capacity <= kMaxFastElementsLength || | 8622 if (!ShouldConvertToSlowElements(new_capacity)) { |
| 8327 !ShouldConvertToSlowElements(new_capacity)) { | |
| 8328 ASSERT(static_cast<uint32_t>(new_capacity) > index); | 8623 ASSERT(static_cast<uint32_t>(new_capacity) > index); |
| 8329 Object* new_elements; | 8624 Object* new_elements; |
| 8330 MaybeObject* maybe = | 8625 MaybeObject* maybe = |
| 8331 SetFastElementsCapacityAndLength(new_capacity, index + 1); | 8626 SetFastElementsCapacityAndLength(new_capacity, index + 1); |
| 8332 if (!maybe->ToObject(&new_elements)) return maybe; | 8627 if (!maybe->ToObject(&new_elements)) return maybe; |
| 8333 FixedArray::cast(new_elements)->set(index, value); | 8628 FixedArray::cast(new_elements)->set(index, value); |
| 8334 return value; | 8629 return value; |
| 8335 } | 8630 } |
| 8336 } | 8631 } |
| 8337 | 8632 |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8425 } | 8720 } |
| 8426 | 8721 |
| 8427 // Attempt to put this object back in fast case. | 8722 // Attempt to put this object back in fast case. |
| 8428 if (ShouldConvertToFastElements()) { | 8723 if (ShouldConvertToFastElements()) { |
| 8429 uint32_t new_length = 0; | 8724 uint32_t new_length = 0; |
| 8430 if (IsJSArray()) { | 8725 if (IsJSArray()) { |
| 8431 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&new_length)); | 8726 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&new_length)); |
| 8432 } else { | 8727 } else { |
| 8433 new_length = dictionary->max_number_key() + 1; | 8728 new_length = dictionary->max_number_key() + 1; |
| 8434 } | 8729 } |
| 8435 MaybeObject* result = | 8730 MaybeObject* result = CanConvertToFastDoubleElements() |
| 8436 SetFastElementsCapacityAndLength(new_length, new_length); | 8731 ? SetFastDoubleElementsCapacityAndLength(new_length, new_length) |
| 8732 : SetFastElementsCapacityAndLength(new_length, new_length); |
| 8437 if (result->IsFailure()) return result; | 8733 if (result->IsFailure()) return result; |
| 8438 #ifdef DEBUG | 8734 #ifdef DEBUG |
| 8439 if (FLAG_trace_normalization) { | 8735 if (FLAG_trace_normalization) { |
| 8440 PrintF("Object elements are fast case again:\n"); | 8736 PrintF("Object elements are fast case again:\n"); |
| 8441 Print(); | 8737 Print(); |
| 8442 } | 8738 } |
| 8443 #endif | 8739 #endif |
| 8444 } | 8740 } |
| 8445 return value; | 8741 return value; |
| 8446 } | 8742 } |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8498 JSArray::cast(this)->set_length(Smi::FromInt(index + 1)); | 8794 JSArray::cast(this)->set_length(Smi::FromInt(index + 1)); |
| 8499 } | 8795 } |
| 8500 } | 8796 } |
| 8501 return value; | 8797 return value; |
| 8502 } | 8798 } |
| 8503 | 8799 |
| 8504 // Allow gap in fast case. | 8800 // Allow gap in fast case. |
| 8505 if ((index - elms_length) < kMaxGap) { | 8801 if ((index - elms_length) < kMaxGap) { |
| 8506 // Try allocating extra space. | 8802 // Try allocating extra space. |
| 8507 int new_capacity = NewElementsCapacity(index+1); | 8803 int new_capacity = NewElementsCapacity(index+1); |
| 8508 if (new_capacity <= kMaxFastElementsLength || | 8804 if (!ShouldConvertToSlowElements(new_capacity)) { |
| 8509 !ShouldConvertToSlowElements(new_capacity)) { | |
| 8510 ASSERT(static_cast<uint32_t>(new_capacity) > index); | 8805 ASSERT(static_cast<uint32_t>(new_capacity) > index); |
| 8511 Object* obj; | 8806 Object* obj; |
| 8512 { MaybeObject* maybe_obj = | 8807 { MaybeObject* maybe_obj = |
| 8513 SetFastDoubleElementsCapacityAndLength(new_capacity, | 8808 SetFastDoubleElementsCapacityAndLength(new_capacity, |
| 8514 index + 1); | 8809 index + 1); |
| 8515 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 8810 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 8516 } | 8811 } |
| 8517 FixedDoubleArray::cast(elements())->set(index, double_value); | 8812 FixedDoubleArray::cast(elements())->set(index, double_value); |
| 8518 return value; | 8813 return value; |
| 8519 } | 8814 } |
| 8520 } | 8815 } |
| 8521 | 8816 |
| 8522 // Otherwise default to slow case. | 8817 // Otherwise default to slow case. |
| 8818 ASSERT(HasFastDoubleElements()); |
| 8819 ASSERT(map()->has_fast_double_elements()); |
| 8820 ASSERT(elements()->IsFixedDoubleArray()); |
| 8523 Object* obj; | 8821 Object* obj; |
| 8524 { MaybeObject* maybe_obj = NormalizeElements(); | 8822 { MaybeObject* maybe_obj = NormalizeElements(); |
| 8525 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 8823 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 8526 } | 8824 } |
| 8527 ASSERT(HasDictionaryElements()); | 8825 ASSERT(HasDictionaryElements()); |
| 8528 return SetElement(index, value, strict_mode, check_prototype); | 8826 return SetElement(index, value, strict_mode, check_prototype); |
| 8529 } | 8827 } |
| 8530 | 8828 |
| 8531 | 8829 |
| 8532 MaybeObject* JSObject::SetElement(uint32_t index, | 8830 MaybeObject* JSObject::SetElement(uint32_t index, |
| 8533 Object* value, | 8831 Object* value, |
| 8534 StrictModeFlag strict_mode, | 8832 StrictModeFlag strict_mode, |
| 8535 bool check_prototype) { | 8833 bool check_prototype) { |
| 8536 // Check access rights if needed. | 8834 // Check access rights if needed. |
| 8537 if (IsAccessCheckNeeded()) { | 8835 if (IsAccessCheckNeeded()) { |
| 8538 Heap* heap = GetHeap(); | 8836 Heap* heap = GetHeap(); |
| 8539 if (!heap->isolate()->MayIndexedAccess(this, index, v8::ACCESS_SET)) { | 8837 if (!heap->isolate()->MayIndexedAccess(this, index, v8::ACCESS_SET)) { |
| 8540 HandleScope scope; | 8838 HandleScope scope(heap->isolate()); |
| 8541 Handle<Object> value_handle(value); | 8839 Handle<Object> value_handle(value); |
| 8542 heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_SET); | 8840 heap->isolate()->ReportFailedAccessCheck(this, v8::ACCESS_SET); |
| 8543 return *value_handle; | 8841 return *value_handle; |
| 8544 } | 8842 } |
| 8545 } | 8843 } |
| 8546 | 8844 |
| 8547 if (IsJSGlobalProxy()) { | 8845 if (IsJSGlobalProxy()) { |
| 8548 Object* proto = GetPrototype(); | 8846 Object* proto = GetPrototype(); |
| 8549 if (proto->IsNull()) return value; | 8847 if (proto->IsNull()) return value; |
| 8550 ASSERT(proto->IsJSGlobalObject()); | 8848 ASSERT(proto->IsJSGlobalObject()); |
| (...skipping 413 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8964 case NON_STRICT_ARGUMENTS_ELEMENTS: | 9262 case NON_STRICT_ARGUMENTS_ELEMENTS: |
| 8965 UNIMPLEMENTED(); | 9263 UNIMPLEMENTED(); |
| 8966 break; | 9264 break; |
| 8967 } | 9265 } |
| 8968 return GetHeap()->undefined_value(); | 9266 return GetHeap()->undefined_value(); |
| 8969 } | 9267 } |
| 8970 | 9268 |
| 8971 | 9269 |
| 8972 bool JSObject::HasDenseElements() { | 9270 bool JSObject::HasDenseElements() { |
| 8973 int capacity = 0; | 9271 int capacity = 0; |
| 8974 int number_of_elements = 0; | 9272 int used = 0; |
| 9273 GetElementsCapacityAndUsage(&capacity, &used); |
| 9274 return (capacity == 0) || (used > (capacity / 2)); |
| 9275 } |
| 8975 | 9276 |
| 8976 FixedArray* backing_store = FixedArray::cast(elements()); | 9277 |
| 9278 void JSObject::GetElementsCapacityAndUsage(int* capacity, int* used) { |
| 9279 *capacity = 0; |
| 9280 *used = 0; |
| 9281 |
| 9282 FixedArrayBase* backing_store_base = FixedArrayBase::cast(elements()); |
| 9283 FixedArray* backing_store = NULL; |
| 8977 switch (GetElementsKind()) { | 9284 switch (GetElementsKind()) { |
| 8978 case NON_STRICT_ARGUMENTS_ELEMENTS: | 9285 case NON_STRICT_ARGUMENTS_ELEMENTS: |
| 8979 backing_store = FixedArray::cast(backing_store->get(1)); | 9286 backing_store_base = |
| 9287 FixedArray::cast(FixedArray::cast(backing_store_base)->get(1)); |
| 9288 backing_store = FixedArray::cast(backing_store_base); |
| 8980 if (backing_store->IsDictionary()) { | 9289 if (backing_store->IsDictionary()) { |
| 8981 NumberDictionary* dictionary = NumberDictionary::cast(backing_store); | 9290 NumberDictionary* dictionary = NumberDictionary::cast(backing_store); |
| 8982 capacity = dictionary->Capacity(); | 9291 *capacity = dictionary->Capacity(); |
| 8983 number_of_elements = dictionary->NumberOfElements(); | 9292 *used = dictionary->NumberOfElements(); |
| 8984 break; | 9293 break; |
| 8985 } | 9294 } |
| 8986 // Fall through. | 9295 // Fall through. |
| 8987 case FAST_ELEMENTS: | 9296 case FAST_ELEMENTS: |
| 8988 capacity = backing_store->length(); | 9297 backing_store = FixedArray::cast(backing_store_base); |
| 8989 for (int i = 0; i < capacity; ++i) { | 9298 *capacity = backing_store->length(); |
| 8990 if (!backing_store->get(i)->IsTheHole()) ++number_of_elements; | 9299 for (int i = 0; i < *capacity; ++i) { |
| 9300 if (!backing_store->get(i)->IsTheHole()) ++(*used); |
| 8991 } | 9301 } |
| 8992 break; | 9302 break; |
| 8993 case DICTIONARY_ELEMENTS: { | 9303 case DICTIONARY_ELEMENTS: { |
| 8994 NumberDictionary* dictionary = NumberDictionary::cast(backing_store); | 9304 NumberDictionary* dictionary = |
| 8995 capacity = dictionary->Capacity(); | 9305 NumberDictionary::cast(FixedArray::cast(elements())); |
| 8996 number_of_elements = dictionary->NumberOfElements(); | 9306 *capacity = dictionary->Capacity(); |
| 9307 *used = dictionary->NumberOfElements(); |
| 8997 break; | 9308 break; |
| 8998 } | 9309 } |
| 8999 case FAST_DOUBLE_ELEMENTS: { | 9310 case FAST_DOUBLE_ELEMENTS: { |
| 9000 FixedDoubleArray* elms = FixedDoubleArray::cast(elements()); | 9311 FixedDoubleArray* elms = FixedDoubleArray::cast(elements()); |
| 9001 capacity = elms->length(); | 9312 *capacity = elms->length(); |
| 9002 for (int i = 0; i < capacity; i++) { | 9313 for (int i = 0; i < *capacity; i++) { |
| 9003 if (!elms->is_the_hole(i)) number_of_elements++; | 9314 if (!elms->is_the_hole(i)) ++(*used); |
| 9004 } | 9315 } |
| 9005 break; | 9316 break; |
| 9006 } | 9317 } |
| 9007 case EXTERNAL_PIXEL_ELEMENTS: | |
| 9008 case EXTERNAL_BYTE_ELEMENTS: | 9318 case EXTERNAL_BYTE_ELEMENTS: |
| 9009 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: | 9319 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: |
| 9010 case EXTERNAL_SHORT_ELEMENTS: | 9320 case EXTERNAL_SHORT_ELEMENTS: |
| 9011 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: | 9321 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: |
| 9012 case EXTERNAL_INT_ELEMENTS: | 9322 case EXTERNAL_INT_ELEMENTS: |
| 9013 case EXTERNAL_UNSIGNED_INT_ELEMENTS: | 9323 case EXTERNAL_UNSIGNED_INT_ELEMENTS: |
| 9014 case EXTERNAL_FLOAT_ELEMENTS: | 9324 case EXTERNAL_FLOAT_ELEMENTS: |
| 9015 case EXTERNAL_DOUBLE_ELEMENTS: { | 9325 case EXTERNAL_DOUBLE_ELEMENTS: |
| 9016 return true; | 9326 case EXTERNAL_PIXEL_ELEMENTS: |
| 9017 } | 9327 // External arrays are considered 100% used. |
| 9328 ExternalArray* external_array = ExternalArray::cast(elements()); |
| 9329 *capacity = external_array->length(); |
| 9330 *used = external_array->length(); |
| 9331 break; |
| 9018 } | 9332 } |
| 9019 return (capacity == 0) || (number_of_elements > (capacity / 2)); | |
| 9020 } | 9333 } |
| 9021 | 9334 |
| 9022 | 9335 |
| 9023 bool JSObject::ShouldConvertToSlowElements(int new_capacity) { | 9336 bool JSObject::ShouldConvertToSlowElements(int new_capacity) { |
| 9024 // Keep the array in fast case if the current backing storage is | 9337 STATIC_ASSERT(kMaxUncheckedOldFastElementsLength <= |
| 9025 // almost filled and if the new capacity is no more than twice the | 9338 kMaxUncheckedFastElementsLength); |
| 9026 // old capacity. | 9339 if (new_capacity <= kMaxUncheckedOldFastElementsLength || |
| 9027 int elements_length = 0; | 9340 (new_capacity <= kMaxUncheckedFastElementsLength && |
| 9028 if (elements()->map() == GetHeap()->non_strict_arguments_elements_map()) { | 9341 GetHeap()->InNewSpace(this))) { |
| 9029 FixedArray* backing_store = FixedArray::cast(elements()); | 9342 return false; |
| 9030 elements_length = FixedArray::cast(backing_store->get(1))->length(); | |
| 9031 } else if (HasFastElements()) { | |
| 9032 elements_length = FixedArray::cast(elements())->length(); | |
| 9033 } else if (HasFastDoubleElements()) { | |
| 9034 elements_length = FixedDoubleArray::cast(elements())->length(); | |
| 9035 } else { | |
| 9036 UNREACHABLE(); | |
| 9037 } | 9343 } |
| 9038 return !HasDenseElements() || ((new_capacity / 2) > elements_length); | 9344 // If the fast-case backing storage takes up roughly three times as |
| 9345 // much space (in machine words) as a dictionary backing storage |
| 9346 // would, the object should have slow elements. |
| 9347 int old_capacity = 0; |
| 9348 int used_elements = 0; |
| 9349 GetElementsCapacityAndUsage(&old_capacity, &used_elements); |
| 9350 int dictionary_size = NumberDictionary::ComputeCapacity(used_elements) * |
| 9351 NumberDictionary::kEntrySize; |
| 9352 return 3 * dictionary_size <= new_capacity; |
| 9039 } | 9353 } |
| 9040 | 9354 |
| 9041 | 9355 |
| 9042 bool JSObject::ShouldConvertToFastElements() { | 9356 bool JSObject::ShouldConvertToFastElements() { |
| 9043 ASSERT(HasDictionaryElements() || HasDictionaryArgumentsElements()); | 9357 ASSERT(HasDictionaryElements() || HasDictionaryArgumentsElements()); |
| 9044 // If the elements are sparse, we should not go back to fast case. | 9358 // If the elements are sparse, we should not go back to fast case. |
| 9045 if (!HasDenseElements()) return false; | 9359 if (!HasDenseElements()) return false; |
| 9046 // An object requiring access checks is never allowed to have fast | 9360 // An object requiring access checks is never allowed to have fast |
| 9047 // elements. If it had fast elements we would skip security checks. | 9361 // elements. If it had fast elements we would skip security checks. |
| 9048 if (IsAccessCheckNeeded()) return false; | 9362 if (IsAccessCheckNeeded()) return false; |
| 9049 | 9363 |
| 9050 FixedArray* elements = FixedArray::cast(this->elements()); | 9364 FixedArray* elements = FixedArray::cast(this->elements()); |
| 9051 NumberDictionary* dictionary = NULL; | 9365 NumberDictionary* dictionary = NULL; |
| 9052 if (elements->map() == GetHeap()->non_strict_arguments_elements_map()) { | 9366 if (elements->map() == GetHeap()->non_strict_arguments_elements_map()) { |
| 9053 dictionary = NumberDictionary::cast(elements->get(1)); | 9367 dictionary = NumberDictionary::cast(elements->get(1)); |
| 9054 } else { | 9368 } else { |
| 9055 dictionary = NumberDictionary::cast(elements); | 9369 dictionary = NumberDictionary::cast(elements); |
| 9056 } | 9370 } |
| 9057 // If an element has been added at a very high index in the elements | 9371 // If an element has been added at a very high index in the elements |
| 9058 // dictionary, we cannot go back to fast case. | 9372 // dictionary, we cannot go back to fast case. |
| 9059 if (dictionary->requires_slow_elements()) return false; | 9373 if (dictionary->requires_slow_elements()) return false; |
| 9060 // If the dictionary backing storage takes up roughly half as much | 9374 // If the dictionary backing storage takes up roughly half as much |
| 9061 // space as a fast-case backing storage would the array should have | 9375 // space (in machine words) as a fast-case backing storage would, |
| 9062 // fast elements. | 9376 // the object should have fast elements. |
| 9063 uint32_t length = 0; | 9377 uint32_t array_size = 0; |
| 9064 if (IsJSArray()) { | 9378 if (IsJSArray()) { |
| 9065 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&length)); | 9379 CHECK(JSArray::cast(this)->length()->ToArrayIndex(&array_size)); |
| 9066 } else { | 9380 } else { |
| 9067 length = dictionary->max_number_key(); | 9381 array_size = dictionary->max_number_key(); |
| 9068 } | 9382 } |
| 9069 return static_cast<uint32_t>(dictionary->Capacity()) >= | 9383 uint32_t dictionary_size = static_cast<uint32_t>(dictionary->Capacity()) * |
| 9070 (length / (2 * NumberDictionary::kEntrySize)); | 9384 NumberDictionary::kEntrySize; |
| 9385 return 2 * dictionary_size >= array_size; |
| 9071 } | 9386 } |
| 9072 | 9387 |
| 9073 | 9388 |
| 9074 bool JSObject::ShouldConvertToFastDoubleElements() { | 9389 bool JSObject::CanConvertToFastDoubleElements() { |
| 9075 if (FLAG_unbox_double_arrays) { | 9390 if (FLAG_unbox_double_arrays) { |
| 9076 ASSERT(HasDictionaryElements()); | 9391 ASSERT(HasDictionaryElements()); |
| 9077 NumberDictionary* dictionary = NumberDictionary::cast(elements()); | 9392 NumberDictionary* dictionary = NumberDictionary::cast(elements()); |
| 9078 for (int i = 0; i < dictionary->Capacity(); i++) { | 9393 for (int i = 0; i < dictionary->Capacity(); i++) { |
| 9079 Object* key = dictionary->KeyAt(i); | 9394 Object* key = dictionary->KeyAt(i); |
| 9080 if (key->IsNumber()) { | 9395 if (key->IsNumber()) { |
| 9081 if (!dictionary->ValueAt(i)->IsNumber()) return false; | 9396 if (!dictionary->ValueAt(i)->IsNumber()) return false; |
| 9082 } | 9397 } |
| 9083 } | 9398 } |
| 9084 return true; | 9399 return true; |
| (...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9254 | 9569 |
| 9255 switch (GetElementsKind()) { | 9570 switch (GetElementsKind()) { |
| 9256 case FAST_ELEMENTS: { | 9571 case FAST_ELEMENTS: { |
| 9257 uint32_t length = IsJSArray() ? | 9572 uint32_t length = IsJSArray() ? |
| 9258 static_cast<uint32_t>( | 9573 static_cast<uint32_t>( |
| 9259 Smi::cast(JSArray::cast(this)->length())->value()) : | 9574 Smi::cast(JSArray::cast(this)->length())->value()) : |
| 9260 static_cast<uint32_t>(FixedArray::cast(elements())->length()); | 9575 static_cast<uint32_t>(FixedArray::cast(elements())->length()); |
| 9261 return (index < length) && | 9576 return (index < length) && |
| 9262 !FixedArray::cast(elements())->get(index)->IsTheHole(); | 9577 !FixedArray::cast(elements())->get(index)->IsTheHole(); |
| 9263 } | 9578 } |
| 9579 case FAST_DOUBLE_ELEMENTS: { |
| 9580 uint32_t length = IsJSArray() ? |
| 9581 static_cast<uint32_t>( |
| 9582 Smi::cast(JSArray::cast(this)->length())->value()) : |
| 9583 static_cast<uint32_t>(FixedDoubleArray::cast(elements())->length()); |
| 9584 return (index < length) && |
| 9585 !FixedDoubleArray::cast(elements())->is_the_hole(index); |
| 9586 break; |
| 9587 } |
| 9264 case EXTERNAL_PIXEL_ELEMENTS: { | 9588 case EXTERNAL_PIXEL_ELEMENTS: { |
| 9265 ExternalPixelArray* pixels = ExternalPixelArray::cast(elements()); | 9589 ExternalPixelArray* pixels = ExternalPixelArray::cast(elements()); |
| 9266 return index < static_cast<uint32_t>(pixels->length()); | 9590 return index < static_cast<uint32_t>(pixels->length()); |
| 9267 } | 9591 } |
| 9268 case EXTERNAL_BYTE_ELEMENTS: | 9592 case EXTERNAL_BYTE_ELEMENTS: |
| 9269 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: | 9593 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: |
| 9270 case EXTERNAL_SHORT_ELEMENTS: | 9594 case EXTERNAL_SHORT_ELEMENTS: |
| 9271 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: | 9595 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: |
| 9272 case EXTERNAL_INT_ELEMENTS: | 9596 case EXTERNAL_INT_ELEMENTS: |
| 9273 case EXTERNAL_UNSIGNED_INT_ELEMENTS: | 9597 case EXTERNAL_UNSIGNED_INT_ELEMENTS: |
| 9274 case EXTERNAL_FLOAT_ELEMENTS: | 9598 case EXTERNAL_FLOAT_ELEMENTS: |
| 9275 case EXTERNAL_DOUBLE_ELEMENTS: { | 9599 case EXTERNAL_DOUBLE_ELEMENTS: { |
| 9276 ExternalArray* array = ExternalArray::cast(elements()); | 9600 ExternalArray* array = ExternalArray::cast(elements()); |
| 9277 return index < static_cast<uint32_t>(array->length()); | 9601 return index < static_cast<uint32_t>(array->length()); |
| 9278 } | 9602 } |
| 9279 case FAST_DOUBLE_ELEMENTS: | |
| 9280 UNREACHABLE(); | |
| 9281 break; | |
| 9282 case DICTIONARY_ELEMENTS: { | 9603 case DICTIONARY_ELEMENTS: { |
| 9283 return element_dictionary()->FindEntry(index) | 9604 return element_dictionary()->FindEntry(index) |
| 9284 != NumberDictionary::kNotFound; | 9605 != NumberDictionary::kNotFound; |
| 9285 } | 9606 } |
| 9286 case NON_STRICT_ARGUMENTS_ELEMENTS: | 9607 case NON_STRICT_ARGUMENTS_ELEMENTS: |
| 9287 UNIMPLEMENTED(); | 9608 UNIMPLEMENTED(); |
| 9288 break; | 9609 break; |
| 9289 } | 9610 } |
| 9290 // All possibilities have been handled above already. | 9611 // All possibilities have been handled above already. |
| 9291 UNREACHABLE(); | 9612 UNREACHABLE(); |
| (...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9492 if (!FixedArray::cast(elements())->get(i)->IsTheHole()) { | 9813 if (!FixedArray::cast(elements())->get(i)->IsTheHole()) { |
| 9493 if (storage != NULL) { | 9814 if (storage != NULL) { |
| 9494 storage->set(counter, Smi::FromInt(i)); | 9815 storage->set(counter, Smi::FromInt(i)); |
| 9495 } | 9816 } |
| 9496 counter++; | 9817 counter++; |
| 9497 } | 9818 } |
| 9498 } | 9819 } |
| 9499 ASSERT(!storage || storage->length() >= counter); | 9820 ASSERT(!storage || storage->length() >= counter); |
| 9500 break; | 9821 break; |
| 9501 } | 9822 } |
| 9823 case FAST_DOUBLE_ELEMENTS: { |
| 9824 int length = IsJSArray() ? |
| 9825 Smi::cast(JSArray::cast(this)->length())->value() : |
| 9826 FixedDoubleArray::cast(elements())->length(); |
| 9827 for (int i = 0; i < length; i++) { |
| 9828 if (!FixedDoubleArray::cast(elements())->is_the_hole(i)) { |
| 9829 if (storage != NULL) { |
| 9830 storage->set(counter, Smi::FromInt(i)); |
| 9831 } |
| 9832 counter++; |
| 9833 } |
| 9834 } |
| 9835 ASSERT(!storage || storage->length() >= counter); |
| 9836 break; |
| 9837 } |
| 9502 case EXTERNAL_PIXEL_ELEMENTS: { | 9838 case EXTERNAL_PIXEL_ELEMENTS: { |
| 9503 int length = ExternalPixelArray::cast(elements())->length(); | 9839 int length = ExternalPixelArray::cast(elements())->length(); |
| 9504 while (counter < length) { | 9840 while (counter < length) { |
| 9505 if (storage != NULL) { | 9841 if (storage != NULL) { |
| 9506 storage->set(counter, Smi::FromInt(counter)); | 9842 storage->set(counter, Smi::FromInt(counter)); |
| 9507 } | 9843 } |
| 9508 counter++; | 9844 counter++; |
| 9509 } | 9845 } |
| 9510 ASSERT(!storage || storage->length() >= counter); | 9846 ASSERT(!storage || storage->length() >= counter); |
| 9511 break; | 9847 break; |
| 9512 } | 9848 } |
| 9513 case EXTERNAL_BYTE_ELEMENTS: | 9849 case EXTERNAL_BYTE_ELEMENTS: |
| 9514 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: | 9850 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: |
| 9515 case EXTERNAL_SHORT_ELEMENTS: | 9851 case EXTERNAL_SHORT_ELEMENTS: |
| 9516 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: | 9852 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: |
| 9517 case EXTERNAL_INT_ELEMENTS: | 9853 case EXTERNAL_INT_ELEMENTS: |
| 9518 case EXTERNAL_UNSIGNED_INT_ELEMENTS: | 9854 case EXTERNAL_UNSIGNED_INT_ELEMENTS: |
| 9519 case EXTERNAL_FLOAT_ELEMENTS: | 9855 case EXTERNAL_FLOAT_ELEMENTS: |
| 9520 case EXTERNAL_DOUBLE_ELEMENTS: { | 9856 case EXTERNAL_DOUBLE_ELEMENTS: { |
| 9521 int length = ExternalArray::cast(elements())->length(); | 9857 int length = ExternalArray::cast(elements())->length(); |
| 9522 while (counter < length) { | 9858 while (counter < length) { |
| 9523 if (storage != NULL) { | 9859 if (storage != NULL) { |
| 9524 storage->set(counter, Smi::FromInt(counter)); | 9860 storage->set(counter, Smi::FromInt(counter)); |
| 9525 } | 9861 } |
| 9526 counter++; | 9862 counter++; |
| 9527 } | 9863 } |
| 9528 ASSERT(!storage || storage->length() >= counter); | 9864 ASSERT(!storage || storage->length() >= counter); |
| 9529 break; | 9865 break; |
| 9530 } | 9866 } |
| 9531 case FAST_DOUBLE_ELEMENTS: | |
| 9532 UNREACHABLE(); | |
| 9533 break; | |
| 9534 case DICTIONARY_ELEMENTS: { | 9867 case DICTIONARY_ELEMENTS: { |
| 9535 if (storage != NULL) { | 9868 if (storage != NULL) { |
| 9536 element_dictionary()->CopyKeysTo(storage, | 9869 element_dictionary()->CopyKeysTo(storage, |
| 9537 filter, | 9870 filter, |
| 9538 NumberDictionary::SORTED); | 9871 NumberDictionary::SORTED); |
| 9539 } | 9872 } |
| 9540 counter += element_dictionary()->NumberOfElementsFilterAttributes(filter); | 9873 counter += element_dictionary()->NumberOfElementsFilterAttributes(filter); |
| 9541 break; | 9874 break; |
| 9542 } | 9875 } |
| 9543 case NON_STRICT_ARGUMENTS_ELEMENTS: { | 9876 case NON_STRICT_ARGUMENTS_ELEMENTS: { |
| (...skipping 433 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9977 void HashTable<Shape, Key>::IterateElements(ObjectVisitor* v) { | 10310 void HashTable<Shape, Key>::IterateElements(ObjectVisitor* v) { |
| 9978 IteratePointers(v, | 10311 IteratePointers(v, |
| 9979 kElementsStartOffset, | 10312 kElementsStartOffset, |
| 9980 kHeaderSize + length() * kPointerSize); | 10313 kHeaderSize + length() * kPointerSize); |
| 9981 } | 10314 } |
| 9982 | 10315 |
| 9983 | 10316 |
| 9984 template<typename Shape, typename Key> | 10317 template<typename Shape, typename Key> |
| 9985 MaybeObject* HashTable<Shape, Key>::Allocate(int at_least_space_for, | 10318 MaybeObject* HashTable<Shape, Key>::Allocate(int at_least_space_for, |
| 9986 PretenureFlag pretenure) { | 10319 PretenureFlag pretenure) { |
| 9987 const int kMinCapacity = 32; | 10320 int capacity = ComputeCapacity(at_least_space_for); |
| 9988 int capacity = RoundUpToPowerOf2(at_least_space_for * 2); | 10321 if (capacity > HashTable::kMaxCapacity) { |
| 9989 if (capacity < kMinCapacity) { | |
| 9990 capacity = kMinCapacity; // Guarantee min capacity. | |
| 9991 } else if (capacity > HashTable::kMaxCapacity) { | |
| 9992 return Failure::OutOfMemoryException(); | 10322 return Failure::OutOfMemoryException(); |
| 9993 } | 10323 } |
| 9994 | 10324 |
| 9995 Object* obj; | 10325 Object* obj; |
| 9996 { MaybeObject* maybe_obj = Isolate::Current()->heap()-> | 10326 { MaybeObject* maybe_obj = Isolate::Current()->heap()-> |
| 9997 AllocateHashTable(EntryToIndex(capacity), pretenure); | 10327 AllocateHashTable(EntryToIndex(capacity), pretenure); |
| 9998 if (!maybe_obj->ToObject(&obj)) return maybe_obj; | 10328 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 9999 } | 10329 } |
| 10000 HashTable::cast(obj)->SetNumberOfElements(0); | 10330 HashTable::cast(obj)->SetNumberOfElements(0); |
| 10001 HashTable::cast(obj)->SetNumberOfDeletedElements(0); | 10331 HashTable::cast(obj)->SetNumberOfDeletedElements(0); |
| (...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10149 | 10479 |
| 10150 // Force instantiation of template instances class. | 10480 // Force instantiation of template instances class. |
| 10151 // Please note this list is compiler dependent. | 10481 // Please note this list is compiler dependent. |
| 10152 | 10482 |
| 10153 template class HashTable<SymbolTableShape, HashTableKey*>; | 10483 template class HashTable<SymbolTableShape, HashTableKey*>; |
| 10154 | 10484 |
| 10155 template class HashTable<CompilationCacheShape, HashTableKey*>; | 10485 template class HashTable<CompilationCacheShape, HashTableKey*>; |
| 10156 | 10486 |
| 10157 template class HashTable<MapCacheShape, HashTableKey*>; | 10487 template class HashTable<MapCacheShape, HashTableKey*>; |
| 10158 | 10488 |
| 10489 template class HashTable<ObjectHashTableShape, JSObject*>; |
| 10490 |
| 10159 template class Dictionary<StringDictionaryShape, String*>; | 10491 template class Dictionary<StringDictionaryShape, String*>; |
| 10160 | 10492 |
| 10161 template class Dictionary<NumberDictionaryShape, uint32_t>; | 10493 template class Dictionary<NumberDictionaryShape, uint32_t>; |
| 10162 | 10494 |
| 10163 template MaybeObject* Dictionary<NumberDictionaryShape, uint32_t>::Allocate( | 10495 template MaybeObject* Dictionary<NumberDictionaryShape, uint32_t>::Allocate( |
| 10164 int); | 10496 int); |
| 10165 | 10497 |
| 10166 template MaybeObject* Dictionary<StringDictionaryShape, String*>::Allocate( | 10498 template MaybeObject* Dictionary<StringDictionaryShape, String*>::Allocate( |
| 10167 int); | 10499 int); |
| 10168 | 10500 |
| (...skipping 902 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 11071 } | 11403 } |
| 11072 } | 11404 } |
| 11073 | 11405 |
| 11074 // Update the number of elements. | 11406 // Update the number of elements. |
| 11075 ElementsRemoved(removed_entries); | 11407 ElementsRemoved(removed_entries); |
| 11076 } | 11408 } |
| 11077 | 11409 |
| 11078 | 11410 |
| 11079 template<typename Shape, typename Key> | 11411 template<typename Shape, typename Key> |
| 11080 Object* Dictionary<Shape, Key>::DeleteProperty(int entry, | 11412 Object* Dictionary<Shape, Key>::DeleteProperty(int entry, |
| 11081 JSObject::DeleteMode mode) { | 11413 JSReceiver::DeleteMode mode) { |
| 11082 Heap* heap = Dictionary<Shape, Key>::GetHeap(); | 11414 Heap* heap = Dictionary<Shape, Key>::GetHeap(); |
| 11083 PropertyDetails details = DetailsAt(entry); | 11415 PropertyDetails details = DetailsAt(entry); |
| 11084 // Ignore attributes if forcing a deletion. | 11416 // Ignore attributes if forcing a deletion. |
| 11085 if (details.IsDontDelete() && mode != JSObject::FORCE_DELETION) { | 11417 if (details.IsDontDelete() && mode != JSReceiver::FORCE_DELETION) { |
| 11086 return heap->false_value(); | 11418 return heap->false_value(); |
| 11087 } | 11419 } |
| 11088 SetEntry(entry, heap->null_value(), heap->null_value()); | 11420 SetEntry(entry, heap->null_value(), heap->null_value()); |
| 11089 HashTable<Shape, Key>::ElementRemoved(); | 11421 HashTable<Shape, Key>::ElementRemoved(); |
| 11090 return heap->true_value(); | 11422 return heap->true_value(); |
| 11091 } | 11423 } |
| 11092 | 11424 |
| 11093 | 11425 |
| 11094 template<typename Shape, typename Key> | 11426 template<typename Shape, typename Key> |
| 11095 MaybeObject* Dictionary<Shape, Key>::Shrink(Key key) { | 11427 MaybeObject* Dictionary<Shape, Key>::Shrink(Key key) { |
| (...skipping 364 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 11460 ASSERT(obj->IsJSObject()); | 11792 ASSERT(obj->IsJSObject()); |
| 11461 | 11793 |
| 11462 descriptors->SetNextEnumerationIndex(NextEnumerationIndex()); | 11794 descriptors->SetNextEnumerationIndex(NextEnumerationIndex()); |
| 11463 // Check that it really works. | 11795 // Check that it really works. |
| 11464 ASSERT(obj->HasFastProperties()); | 11796 ASSERT(obj->HasFastProperties()); |
| 11465 | 11797 |
| 11466 return obj; | 11798 return obj; |
| 11467 } | 11799 } |
| 11468 | 11800 |
| 11469 | 11801 |
| 11802 Object* ObjectHashTable::Lookup(JSObject* key) { |
| 11803 // If the object does not have an identity hash, it was never used as a key. |
| 11804 MaybeObject* maybe_hash = key->GetIdentityHash(JSObject::OMIT_CREATION); |
| 11805 if (maybe_hash->IsFailure()) return GetHeap()->undefined_value(); |
| 11806 int entry = FindEntry(key); |
| 11807 if (entry == kNotFound) return GetHeap()->undefined_value(); |
| 11808 return get(EntryToIndex(entry) + 1); |
| 11809 } |
| 11810 |
| 11811 |
| 11812 MaybeObject* ObjectHashTable::Put(JSObject* key, Object* value) { |
| 11813 // Make sure the key object has an identity hash code. |
| 11814 int hash; |
| 11815 { MaybeObject* maybe_hash = key->GetIdentityHash(JSObject::ALLOW_CREATION); |
| 11816 if (maybe_hash->IsFailure()) return maybe_hash; |
| 11817 hash = Smi::cast(maybe_hash->ToObjectUnchecked())->value(); |
| 11818 } |
| 11819 int entry = FindEntry(key); |
| 11820 |
| 11821 // Check whether to perform removal operation. |
| 11822 if (value->IsUndefined()) { |
| 11823 if (entry == kNotFound) return this; |
| 11824 RemoveEntry(entry); |
| 11825 return Shrink(key); |
| 11826 } |
| 11827 |
| 11828 // Key is already in table, just overwrite value. |
| 11829 if (entry != kNotFound) { |
| 11830 set(EntryToIndex(entry) + 1, value); |
| 11831 return this; |
| 11832 } |
| 11833 |
| 11834 // Check whether the hash table should be extended. |
| 11835 Object* obj; |
| 11836 { MaybeObject* maybe_obj = EnsureCapacity(1, key); |
| 11837 if (!maybe_obj->ToObject(&obj)) return maybe_obj; |
| 11838 } |
| 11839 ObjectHashTable* table = ObjectHashTable::cast(obj); |
| 11840 table->AddEntry(table->FindInsertionEntry(hash), key, value); |
| 11841 return table; |
| 11842 } |
| 11843 |
| 11844 |
| 11845 void ObjectHashTable::AddEntry(int entry, JSObject* key, Object* value) { |
| 11846 set(EntryToIndex(entry), key); |
| 11847 set(EntryToIndex(entry) + 1, value); |
| 11848 ElementAdded(); |
| 11849 } |
| 11850 |
| 11851 |
| 11852 void ObjectHashTable::RemoveEntry(int entry) { |
| 11853 Object* null_value = GetHeap()->null_value(); |
| 11854 set(EntryToIndex(entry), null_value); |
| 11855 set(EntryToIndex(entry) + 1, null_value); |
| 11856 ElementRemoved(); |
| 11857 } |
| 11858 |
| 11859 |
| 11470 #ifdef ENABLE_DEBUGGER_SUPPORT | 11860 #ifdef ENABLE_DEBUGGER_SUPPORT |
| 11471 // Check if there is a break point at this code position. | 11861 // Check if there is a break point at this code position. |
| 11472 bool DebugInfo::HasBreakPoint(int code_position) { | 11862 bool DebugInfo::HasBreakPoint(int code_position) { |
| 11473 // Get the break point info object for this code position. | 11863 // Get the break point info object for this code position. |
| 11474 Object* break_point_info = GetBreakPointInfo(code_position); | 11864 Object* break_point_info = GetBreakPointInfo(code_position); |
| 11475 | 11865 |
| 11476 // If there is no break point info object or no break points in the break | 11866 // If there is no break point info object or no break points in the break |
| 11477 // point info object there is no break point at this code position. | 11867 // point info object there is no break point at this code position. |
| 11478 if (break_point_info->IsUndefined()) return false; | 11868 if (break_point_info->IsUndefined()) return false; |
| 11479 return BreakPointInfo::cast(break_point_info)->GetBreakPointCount() > 0; | 11869 return BreakPointInfo::cast(break_point_info)->GetBreakPointCount() > 0; |
| (...skipping 234 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 11714 if (break_point_objects()->IsUndefined()) return 0; | 12104 if (break_point_objects()->IsUndefined()) return 0; |
| 11715 // Single beak point. | 12105 // Single beak point. |
| 11716 if (!break_point_objects()->IsFixedArray()) return 1; | 12106 if (!break_point_objects()->IsFixedArray()) return 1; |
| 11717 // Multiple break points. | 12107 // Multiple break points. |
| 11718 return FixedArray::cast(break_point_objects())->length(); | 12108 return FixedArray::cast(break_point_objects())->length(); |
| 11719 } | 12109 } |
| 11720 #endif | 12110 #endif |
| 11721 | 12111 |
| 11722 | 12112 |
| 11723 } } // namespace v8::internal | 12113 } } // namespace v8::internal |
| OLD | NEW |