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/v8.h" | 5 #include "src/v8.h" |
6 | 6 |
7 #include "src/api.h" | 7 #include "src/api.h" |
8 #include "src/arguments.h" | 8 #include "src/arguments.h" |
9 #include "src/base/once.h" | 9 #include "src/base/once.h" |
10 #include "src/bootstrapper.h" | 10 #include "src/bootstrapper.h" |
(...skipping 236 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
247 | 247 |
248 | 248 |
249 static bool ArrayPrototypeHasNoElements(Heap* heap, | 249 static bool ArrayPrototypeHasNoElements(Heap* heap, |
250 Context* native_context, | 250 Context* native_context, |
251 JSObject* array_proto) { | 251 JSObject* array_proto) { |
252 DisallowHeapAllocation no_gc; | 252 DisallowHeapAllocation no_gc; |
253 // This method depends on non writability of Object and Array prototype | 253 // This method depends on non writability of Object and Array prototype |
254 // fields. | 254 // fields. |
255 if (array_proto->elements() != heap->empty_fixed_array()) return false; | 255 if (array_proto->elements() != heap->empty_fixed_array()) return false; |
256 // Object.prototype | 256 // Object.prototype |
257 Object* proto = array_proto->GetPrototype(); | 257 PrototypeIterator iter(heap->isolate(), array_proto); |
258 if (proto == heap->null_value()) return false; | 258 if (iter.IsAtEnd()) { |
259 array_proto = JSObject::cast(proto); | 259 return false; |
| 260 } |
| 261 array_proto = JSObject::cast(iter.GetCurrent()); |
260 if (array_proto != native_context->initial_object_prototype()) return false; | 262 if (array_proto != native_context->initial_object_prototype()) return false; |
261 if (array_proto->elements() != heap->empty_fixed_array()) return false; | 263 if (array_proto->elements() != heap->empty_fixed_array()) return false; |
262 return array_proto->GetPrototype()->IsNull(); | 264 iter.Advance(); |
| 265 return iter.IsAtEnd(); |
263 } | 266 } |
264 | 267 |
265 | 268 |
266 // Returns empty handle if not applicable. | 269 // Returns empty handle if not applicable. |
267 MUST_USE_RESULT | 270 MUST_USE_RESULT |
268 static inline MaybeHandle<FixedArrayBase> EnsureJSArrayWithWritableFastElements( | 271 static inline MaybeHandle<FixedArrayBase> EnsureJSArrayWithWritableFastElements( |
269 Isolate* isolate, | 272 Isolate* isolate, |
270 Handle<Object> receiver, | 273 Handle<Object> receiver, |
271 Arguments* args, | 274 Arguments* args, |
272 int first_added_arg) { | 275 int first_added_arg) { |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
325 } | 328 } |
326 | 329 |
327 | 330 |
328 static inline bool IsJSArrayFastElementMovingAllowed(Heap* heap, | 331 static inline bool IsJSArrayFastElementMovingAllowed(Heap* heap, |
329 JSArray* receiver) { | 332 JSArray* receiver) { |
330 if (!FLAG_clever_optimizations) return false; | 333 if (!FLAG_clever_optimizations) return false; |
331 DisallowHeapAllocation no_gc; | 334 DisallowHeapAllocation no_gc; |
332 Context* native_context = heap->isolate()->context()->native_context(); | 335 Context* native_context = heap->isolate()->context()->native_context(); |
333 JSObject* array_proto = | 336 JSObject* array_proto = |
334 JSObject::cast(native_context->array_function()->prototype()); | 337 JSObject::cast(native_context->array_function()->prototype()); |
335 return receiver->GetPrototype() == array_proto && | 338 PrototypeIterator iter(heap->isolate(), receiver); |
| 339 return iter.GetCurrent() == array_proto && |
336 ArrayPrototypeHasNoElements(heap, native_context, array_proto); | 340 ArrayPrototypeHasNoElements(heap, native_context, array_proto); |
337 } | 341 } |
338 | 342 |
339 | 343 |
340 MUST_USE_RESULT static Object* CallJsBuiltin( | 344 MUST_USE_RESULT static Object* CallJsBuiltin( |
341 Isolate* isolate, | 345 Isolate* isolate, |
342 const char* name, | 346 const char* name, |
343 BuiltinArguments<NO_EXTRA_ARGUMENTS> args) { | 347 BuiltinArguments<NO_EXTRA_ARGUMENTS> args) { |
344 HandleScope handleScope(isolate); | 348 HandleScope handleScope(isolate); |
345 | 349 |
(...skipping 647 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
993 if (!ArrayPrototypeHasNoElements(heap, native_context, array_proto)) { | 997 if (!ArrayPrototypeHasNoElements(heap, native_context, array_proto)) { |
994 AllowHeapAllocation allow_allocation; | 998 AllowHeapAllocation allow_allocation; |
995 return CallJsBuiltin(isolate, "ArrayConcatJS", args); | 999 return CallJsBuiltin(isolate, "ArrayConcatJS", args); |
996 } | 1000 } |
997 | 1001 |
998 // Iterate through all the arguments performing checks | 1002 // Iterate through all the arguments performing checks |
999 // and calculating total length. | 1003 // and calculating total length. |
1000 bool is_holey = false; | 1004 bool is_holey = false; |
1001 for (int i = 0; i < n_arguments; i++) { | 1005 for (int i = 0; i < n_arguments; i++) { |
1002 Object* arg = args[i]; | 1006 Object* arg = args[i]; |
1003 if (!arg->IsJSArray() || | 1007 PrototypeIterator iter(isolate, arg); |
1004 !JSArray::cast(arg)->HasFastElements() || | 1008 if (!arg->IsJSArray() || !JSArray::cast(arg)->HasFastElements() || |
1005 JSArray::cast(arg)->GetPrototype() != array_proto) { | 1009 iter.GetCurrent() != array_proto) { |
1006 AllowHeapAllocation allow_allocation; | 1010 AllowHeapAllocation allow_allocation; |
1007 return CallJsBuiltin(isolate, "ArrayConcatJS", args); | 1011 return CallJsBuiltin(isolate, "ArrayConcatJS", args); |
1008 } | 1012 } |
1009 int len = Smi::cast(JSArray::cast(arg)->length())->value(); | 1013 int len = Smi::cast(JSArray::cast(arg)->length())->value(); |
1010 | 1014 |
1011 // We shouldn't overflow when adding another len. | 1015 // We shouldn't overflow when adding another len. |
1012 const int kHalfOfMaxInt = 1 << (kBitsPerInt - 2); | 1016 const int kHalfOfMaxInt = 1 << (kBitsPerInt - 2); |
1013 STATIC_ASSERT(FixedArray::kMaxLength < kHalfOfMaxInt); | 1017 STATIC_ASSERT(FixedArray::kMaxLength < kHalfOfMaxInt); |
1014 USE(kHalfOfMaxInt); | 1018 USE(kHalfOfMaxInt); |
1015 result_len += len; | 1019 result_len += len; |
(...skipping 697 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1713 } | 1717 } |
1714 BUILTIN_LIST_C(DEFINE_BUILTIN_ACCESSOR_C) | 1718 BUILTIN_LIST_C(DEFINE_BUILTIN_ACCESSOR_C) |
1715 BUILTIN_LIST_A(DEFINE_BUILTIN_ACCESSOR_A) | 1719 BUILTIN_LIST_A(DEFINE_BUILTIN_ACCESSOR_A) |
1716 BUILTIN_LIST_H(DEFINE_BUILTIN_ACCESSOR_H) | 1720 BUILTIN_LIST_H(DEFINE_BUILTIN_ACCESSOR_H) |
1717 BUILTIN_LIST_DEBUG_A(DEFINE_BUILTIN_ACCESSOR_A) | 1721 BUILTIN_LIST_DEBUG_A(DEFINE_BUILTIN_ACCESSOR_A) |
1718 #undef DEFINE_BUILTIN_ACCESSOR_C | 1722 #undef DEFINE_BUILTIN_ACCESSOR_C |
1719 #undef DEFINE_BUILTIN_ACCESSOR_A | 1723 #undef DEFINE_BUILTIN_ACCESSOR_A |
1720 | 1724 |
1721 | 1725 |
1722 } } // namespace v8::internal | 1726 } } // namespace v8::internal |
OLD | NEW |