| OLD | NEW | 
|---|
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. | 
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be | 
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. | 
| 4 | 4 | 
| 5 #include "src/builtins.h" | 5 #include "src/builtins.h" | 
| 6 | 6 | 
| 7 #include "src/api.h" | 7 #include "src/api.h" | 
| 8 #include "src/api-arguments.h" | 8 #include "src/api-arguments.h" | 
| 9 #include "src/api-natives.h" | 9 #include "src/api-natives.h" | 
| 10 #include "src/base/once.h" | 10 #include "src/base/once.h" | 
| (...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 207                                      int* out) { | 207                                      int* out) { | 
| 208   Map* arguments_map = isolate->native_context()->sloppy_arguments_map(); | 208   Map* arguments_map = isolate->native_context()->sloppy_arguments_map(); | 
| 209   if (object->map() != arguments_map) return false; | 209   if (object->map() != arguments_map) return false; | 
| 210   DCHECK(object->HasFastElements()); | 210   DCHECK(object->HasFastElements()); | 
| 211   Object* len_obj = object->InObjectPropertyAt(JSArgumentsObject::kLengthIndex); | 211   Object* len_obj = object->InObjectPropertyAt(JSArgumentsObject::kLengthIndex); | 
| 212   if (!len_obj->IsSmi()) return false; | 212   if (!len_obj->IsSmi()) return false; | 
| 213   *out = Max(0, Smi::cast(len_obj)->value()); | 213   *out = Max(0, Smi::cast(len_obj)->value()); | 
| 214   return *out <= object->elements()->length(); | 214   return *out <= object->elements()->length(); | 
| 215 } | 215 } | 
| 216 | 216 | 
| 217 | 217 inline bool PrototypeHasNoElements(Isolate* isolate, JSObject* object) { | 
| 218 inline bool PrototypeHasNoElements(PrototypeIterator* iter) { |  | 
| 219   DisallowHeapAllocation no_gc; | 218   DisallowHeapAllocation no_gc; | 
| 220   for (; !iter->IsAtEnd(); iter->Advance()) { | 219   HeapObject* prototype = HeapObject::cast(object->map()->prototype()); | 
| 221     if (iter->GetCurrent()->IsJSProxy()) return false; | 220   HeapObject* null = isolate->heap()->null_value(); | 
| 222     JSObject* current = iter->GetCurrent<JSObject>(); | 221   HeapObject* empty = isolate->heap()->empty_fixed_array(); | 
| 223     if (current->IsAccessCheckNeeded()) return false; | 222   while (prototype != null) { | 
| 224     if (current->HasIndexedInterceptor()) return false; | 223     Map* map = prototype->map(); | 
| 225     if (current->HasStringWrapperElements()) return false; | 224     if (map->instance_type() <= LAST_CUSTOM_ELEMENTS_RECEIVER) return false; | 
| 226     if (current->elements()->length() != 0) return false; | 225     if (JSObject::cast(prototype)->elements() != empty) return false; | 
|  | 226     prototype = HeapObject::cast(map->prototype()); | 
| 227   } | 227   } | 
| 228   return true; | 228   return true; | 
| 229 } | 229 } | 
| 230 | 230 | 
| 231 inline bool IsJSArrayFastElementMovingAllowed(Isolate* isolate, | 231 inline bool IsJSArrayFastElementMovingAllowed(Isolate* isolate, | 
| 232                                               JSArray* receiver) { | 232                                               JSArray* receiver) { | 
| 233   DisallowHeapAllocation no_gc; | 233   return PrototypeHasNoElements(isolate, receiver); | 
| 234   // If the array prototype chain is intact (and free of elements), and if the |  | 
| 235   // receiver's prototype is the array prototype, then we are done. |  | 
| 236   Object* prototype = receiver->map()->prototype(); |  | 
| 237   if (prototype->IsJSArray() && |  | 
| 238       isolate->is_initial_array_prototype(JSArray::cast(prototype)) && |  | 
| 239       isolate->IsFastArrayConstructorPrototypeChainIntact()) { |  | 
| 240     return true; |  | 
| 241   } |  | 
| 242   // Slow case. |  | 
| 243   PrototypeIterator iter(isolate, receiver); |  | 
| 244   return PrototypeHasNoElements(&iter); |  | 
| 245 } | 234 } | 
| 246 | 235 | 
| 247 inline bool HasSimpleElements(JSObject* current) { | 236 inline bool HasSimpleElements(JSObject* current) { | 
| 248   if (current->IsAccessCheckNeeded()) return false; | 237   return current->map()->instance_type() > LAST_CUSTOM_ELEMENTS_RECEIVER && | 
| 249   if (current->HasIndexedInterceptor()) return false; | 238          !current->GetElementsAccessor()->HasAccessors(current); | 
| 250   if (current->HasStringWrapperElements()) return false; |  | 
| 251   if (current->GetElementsAccessor()->HasAccessors(current)) return false; |  | 
| 252   return true; |  | 
| 253 } | 239 } | 
| 254 | 240 | 
| 255 inline bool HasOnlySimpleReceiverElements(Isolate* isolate, | 241 inline bool HasOnlySimpleReceiverElements(Isolate* isolate, | 
| 256                                           JSReceiver* receiver) { | 242                                           JSObject* receiver) { | 
| 257   // Check that we have no accessors on the receiver's elements. | 243   // Check that we have no accessors on the receiver's elements. | 
| 258   JSObject* object = JSObject::cast(receiver); | 244   if (!HasSimpleElements(receiver)) return false; | 
| 259   if (!HasSimpleElements(object)) return false; | 245   return PrototypeHasNoElements(isolate, receiver); | 
| 260   // Check that ther are not elements on the prototype. |  | 
| 261   DisallowHeapAllocation no_gc; |  | 
| 262   PrototypeIterator iter(isolate, receiver); |  | 
| 263   return PrototypeHasNoElements(&iter); |  | 
| 264 } | 246 } | 
| 265 | 247 | 
| 266 inline bool HasOnlySimpleElements(Isolate* isolate, JSReceiver* receiver) { | 248 inline bool HasOnlySimpleElements(Isolate* isolate, JSReceiver* receiver) { | 
| 267   // Check that ther are not elements on the prototype. |  | 
| 268   DisallowHeapAllocation no_gc; | 249   DisallowHeapAllocation no_gc; | 
| 269   PrototypeIterator iter(isolate, receiver, | 250   PrototypeIterator iter(isolate, receiver, | 
| 270                          PrototypeIterator::START_AT_RECEIVER); | 251                          PrototypeIterator::START_AT_RECEIVER); | 
| 271   for (; !iter.IsAtEnd(); iter.Advance()) { | 252   for (; !iter.IsAtEnd(); iter.Advance()) { | 
| 272     if (iter.GetCurrent()->IsJSProxy()) return false; | 253     if (iter.GetCurrent()->IsJSProxy()) return false; | 
| 273     JSObject* current = iter.GetCurrent<JSObject>(); | 254     JSObject* current = iter.GetCurrent<JSObject>(); | 
| 274     if (!HasSimpleElements(current)) return false; | 255     if (!HasSimpleElements(current)) return false; | 
| 275   } | 256   } | 
| 276   return true; | 257   return true; | 
| 277 } | 258 } | 
| 278 | 259 | 
| 279 // Returns |false| if not applicable. | 260 // Returns |false| if not applicable. | 
| 280 MUST_USE_RESULT | 261 MUST_USE_RESULT | 
| 281 inline bool EnsureJSArrayWithWritableFastElements(Isolate* isolate, | 262 inline bool EnsureJSArrayWithWritableFastElements(Isolate* isolate, | 
| 282                                                   Handle<Object> receiver, | 263                                                   Handle<Object> receiver, | 
| 283                                                   Arguments* args, | 264                                                   Arguments* args, | 
| 284                                                   int first_added_arg) { | 265                                                   int first_added_arg) { | 
| 285   if (!receiver->IsJSArray()) return false; | 266   if (!receiver->IsJSArray()) return false; | 
| 286   Handle<JSArray> array = Handle<JSArray>::cast(receiver); | 267   Handle<JSArray> array = Handle<JSArray>::cast(receiver); | 
| 287   // If there may be elements accessors in the prototype chain, the fast path |  | 
| 288   // cannot be used if there arguments to add to the array. |  | 
| 289   if (args != nullptr && !IsJSArrayFastElementMovingAllowed(isolate, *array)) { |  | 
| 290     return false; |  | 
| 291   } |  | 
| 292   ElementsKind origin_kind = array->GetElementsKind(); | 268   ElementsKind origin_kind = array->GetElementsKind(); | 
| 293   if (IsDictionaryElementsKind(origin_kind)) return false; | 269   if (IsDictionaryElementsKind(origin_kind)) return false; | 
| 294   if (array->map()->is_observed()) return false; | 270   if (array->map()->is_observed()) return false; | 
| 295   if (!array->map()->is_extensible()) return false; | 271   if (!array->map()->is_extensible()) return false; | 
| 296   if (args == nullptr) return true; | 272   if (args == nullptr) return true; | 
| 297 | 273 | 
|  | 274   // If there may be elements accessors in the prototype chain, the fast path | 
|  | 275   // cannot be used if there arguments to add to the array. | 
|  | 276   if (!IsJSArrayFastElementMovingAllowed(isolate, *array)) return false; | 
|  | 277 | 
| 298   // Adding elements to the array prototype would break code that makes sure | 278   // Adding elements to the array prototype would break code that makes sure | 
| 299   // it has no elements. Handle that elsewhere. | 279   // it has no elements. Handle that elsewhere. | 
| 300   if (isolate->IsAnyInitialArrayPrototype(array)) return false; | 280   if (isolate->IsAnyInitialArrayPrototype(array)) return false; | 
| 301 | 281 | 
| 302   // Need to ensure that the arguments passed in args can be contained in | 282   // Need to ensure that the arguments passed in args can be contained in | 
| 303   // the array. | 283   // the array. | 
| 304   int args_length = args->length(); | 284   int args_length = args->length(); | 
| 305   if (first_added_arg >= args_length) return true; | 285   if (first_added_arg >= args_length) return true; | 
| 306 | 286 | 
| 307   if (IsFastObjectElementsKind(origin_kind)) return true; | 287   if (IsFastObjectElementsKind(origin_kind)) return true; | 
| 308   ElementsKind target_kind = origin_kind; | 288   ElementsKind target_kind = origin_kind; | 
| 309   { | 289   { | 
| 310     DisallowHeapAllocation no_gc; | 290     DisallowHeapAllocation no_gc; | 
| 311     int arg_count = args_length - first_added_arg; | 291     for (int i = first_added_arg; i < args_length; i++) { | 
| 312     Object** arguments = args->arguments() - first_added_arg - (arg_count - 1); | 292       Object* arg = (*args)[i]; | 
| 313     for (int i = 0; i < arg_count; i++) { |  | 
| 314       Object* arg = arguments[i]; |  | 
| 315       if (arg->IsHeapObject()) { | 293       if (arg->IsHeapObject()) { | 
| 316         if (arg->IsHeapNumber()) { | 294         if (arg->IsHeapNumber()) { | 
| 317           target_kind = FAST_DOUBLE_ELEMENTS; | 295           target_kind = FAST_DOUBLE_ELEMENTS; | 
| 318         } else { | 296         } else { | 
| 319           target_kind = FAST_ELEMENTS; | 297           target_kind = FAST_ELEMENTS; | 
| 320           break; | 298           break; | 
| 321         } | 299         } | 
| 322       } | 300       } | 
| 323     } | 301     } | 
| 324   } | 302   } | 
| (...skipping 4212 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 4537 BUILTIN_LIST_C(DEFINE_BUILTIN_ACCESSOR_C) | 4515 BUILTIN_LIST_C(DEFINE_BUILTIN_ACCESSOR_C) | 
| 4538 BUILTIN_LIST_A(DEFINE_BUILTIN_ACCESSOR_A) | 4516 BUILTIN_LIST_A(DEFINE_BUILTIN_ACCESSOR_A) | 
| 4539 BUILTIN_LIST_H(DEFINE_BUILTIN_ACCESSOR_H) | 4517 BUILTIN_LIST_H(DEFINE_BUILTIN_ACCESSOR_H) | 
| 4540 BUILTIN_LIST_DEBUG_A(DEFINE_BUILTIN_ACCESSOR_A) | 4518 BUILTIN_LIST_DEBUG_A(DEFINE_BUILTIN_ACCESSOR_A) | 
| 4541 #undef DEFINE_BUILTIN_ACCESSOR_C | 4519 #undef DEFINE_BUILTIN_ACCESSOR_C | 
| 4542 #undef DEFINE_BUILTIN_ACCESSOR_A | 4520 #undef DEFINE_BUILTIN_ACCESSOR_A | 
| 4543 | 4521 | 
| 4544 | 4522 | 
| 4545 }  // namespace internal | 4523 }  // namespace internal | 
| 4546 }  // namespace v8 | 4524 }  // namespace v8 | 
| OLD | NEW | 
|---|