| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 260 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 271 new_elms->address(), | 271 new_elms->address(), |
| 272 new_elms->Size()); | 272 new_elms->Size()); |
| 273 } | 273 } |
| 274 return new_elms; | 274 return new_elms; |
| 275 } | 275 } |
| 276 | 276 |
| 277 | 277 |
| 278 static bool ArrayPrototypeHasNoElements(Heap* heap, | 278 static bool ArrayPrototypeHasNoElements(Heap* heap, |
| 279 Context* native_context, | 279 Context* native_context, |
| 280 JSObject* array_proto) { | 280 JSObject* array_proto) { |
| 281 DisallowHeapAllocation no_gc; |
| 281 // This method depends on non writability of Object and Array prototype | 282 // This method depends on non writability of Object and Array prototype |
| 282 // fields. | 283 // fields. |
| 283 if (array_proto->elements() != heap->empty_fixed_array()) return false; | 284 if (array_proto->elements() != heap->empty_fixed_array()) return false; |
| 284 // Object.prototype | 285 // Object.prototype |
| 285 Object* proto = array_proto->GetPrototype(); | 286 Object* proto = array_proto->GetPrototype(); |
| 286 if (proto == heap->null_value()) return false; | 287 if (proto == heap->null_value()) return false; |
| 287 array_proto = JSObject::cast(proto); | 288 array_proto = JSObject::cast(proto); |
| 288 if (array_proto != native_context->initial_object_prototype()) return false; | 289 if (array_proto != native_context->initial_object_prototype()) return false; |
| 289 if (array_proto->elements() != heap->empty_fixed_array()) return false; | 290 if (array_proto->elements() != heap->empty_fixed_array()) return false; |
| 290 return array_proto->GetPrototype()->IsNull(); | 291 return array_proto->GetPrototype()->IsNull(); |
| (...skipping 26 matching lines...) Expand all Loading... |
| 317 } | 318 } |
| 318 | 319 |
| 319 // Need to ensure that the arguments passed in args can be contained in | 320 // Need to ensure that the arguments passed in args can be contained in |
| 320 // the array. | 321 // the array. |
| 321 int args_length = args->length(); | 322 int args_length = args->length(); |
| 322 if (first_added_arg >= args_length) return handle(array->elements(), isolate); | 323 if (first_added_arg >= args_length) return handle(array->elements(), isolate); |
| 323 | 324 |
| 324 ElementsKind origin_kind = array->map()->elements_kind(); | 325 ElementsKind origin_kind = array->map()->elements_kind(); |
| 325 ASSERT(!IsFastObjectElementsKind(origin_kind)); | 326 ASSERT(!IsFastObjectElementsKind(origin_kind)); |
| 326 ElementsKind target_kind = origin_kind; | 327 ElementsKind target_kind = origin_kind; |
| 327 int arg_count = args->length() - first_added_arg; | 328 { |
| 328 Object** arguments = args->arguments() - first_added_arg - (arg_count - 1); | 329 DisallowHeapAllocation no_gc; |
| 329 for (int i = 0; i < arg_count; i++) { | 330 int arg_count = args->length() - first_added_arg; |
| 330 Object* arg = arguments[i]; | 331 Object** arguments = args->arguments() - first_added_arg - (arg_count - 1); |
| 331 if (arg->IsHeapObject()) { | 332 for (int i = 0; i < arg_count; i++) { |
| 332 if (arg->IsHeapNumber()) { | 333 Object* arg = arguments[i]; |
| 333 target_kind = FAST_DOUBLE_ELEMENTS; | 334 if (arg->IsHeapObject()) { |
| 334 } else { | 335 if (arg->IsHeapNumber()) { |
| 335 target_kind = FAST_ELEMENTS; | 336 target_kind = FAST_DOUBLE_ELEMENTS; |
| 336 break; | 337 } else { |
| 338 target_kind = FAST_ELEMENTS; |
| 339 break; |
| 340 } |
| 337 } | 341 } |
| 338 } | 342 } |
| 339 } | 343 } |
| 340 if (target_kind != origin_kind) { | 344 if (target_kind != origin_kind) { |
| 341 JSObject::TransitionElementsKind(array, target_kind); | 345 JSObject::TransitionElementsKind(array, target_kind); |
| 342 return handle(array->elements(), isolate); | 346 return handle(array->elements(), isolate); |
| 343 } | 347 } |
| 344 return elms; | 348 return elms; |
| 345 } | 349 } |
| 346 | 350 |
| 347 | 351 |
| 348 // TODO(ishell): Handlify when all Array* builtins are handlified. | |
| 349 static inline bool IsJSArrayFastElementMovingAllowed(Heap* heap, | 352 static inline bool IsJSArrayFastElementMovingAllowed(Heap* heap, |
| 350 JSArray* receiver) { | 353 JSArray* receiver) { |
| 351 if (!FLAG_clever_optimizations) return false; | 354 if (!FLAG_clever_optimizations) return false; |
| 355 DisallowHeapAllocation no_gc; |
| 352 Context* native_context = heap->isolate()->context()->native_context(); | 356 Context* native_context = heap->isolate()->context()->native_context(); |
| 353 JSObject* array_proto = | 357 JSObject* array_proto = |
| 354 JSObject::cast(native_context->array_function()->prototype()); | 358 JSObject::cast(native_context->array_function()->prototype()); |
| 355 return receiver->GetPrototype() == array_proto && | 359 return receiver->GetPrototype() == array_proto && |
| 356 ArrayPrototypeHasNoElements(heap, native_context, array_proto); | 360 ArrayPrototypeHasNoElements(heap, native_context, array_proto); |
| 357 } | 361 } |
| 358 | 362 |
| 359 | 363 |
| 360 MUST_USE_RESULT static MaybeObject* CallJsBuiltin( | 364 MUST_USE_RESULT static MaybeObject* CallJsBuiltin( |
| 361 Isolate* isolate, | 365 Isolate* isolate, |
| (...skipping 618 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 980 } | 984 } |
| 981 // Set the length. | 985 // Set the length. |
| 982 array->set_length(Smi::FromInt(new_length)); | 986 array->set_length(Smi::FromInt(new_length)); |
| 983 | 987 |
| 984 return *result_array; | 988 return *result_array; |
| 985 } | 989 } |
| 986 | 990 |
| 987 | 991 |
| 988 BUILTIN(ArrayConcat) { | 992 BUILTIN(ArrayConcat) { |
| 989 HandleScope scope(isolate); | 993 HandleScope scope(isolate); |
| 990 Heap* heap = isolate->heap(); | |
| 991 Handle<Context> native_context(isolate->context()->native_context(), isolate); | |
| 992 Handle<JSObject> array_proto( | |
| 993 JSObject::cast(native_context->array_function()->prototype()), isolate); | |
| 994 if (!ArrayPrototypeHasNoElements(heap, *native_context, *array_proto)) { | |
| 995 return CallJsBuiltin(isolate, "ArrayConcat", args); | |
| 996 } | |
| 997 | 994 |
| 998 // Iterate through all the arguments performing checks | |
| 999 // and calculating total length. | |
| 1000 int n_arguments = args.length(); | 995 int n_arguments = args.length(); |
| 1001 int result_len = 0; | 996 int result_len = 0; |
| 1002 ElementsKind elements_kind = GetInitialFastElementsKind(); | 997 ElementsKind elements_kind = GetInitialFastElementsKind(); |
| 1003 bool has_double = false; | 998 bool has_double = false; |
| 1004 bool is_holey = false; | 999 { |
| 1005 for (int i = 0; i < n_arguments; i++) { | |
| 1006 DisallowHeapAllocation no_gc; | 1000 DisallowHeapAllocation no_gc; |
| 1007 Object* arg = args[i]; | 1001 Heap* heap = isolate->heap(); |
| 1008 if (!arg->IsJSArray() || | 1002 Context* native_context = isolate->context()->native_context(); |
| 1009 !JSArray::cast(arg)->HasFastElements() || | 1003 JSObject* array_proto = |
| 1010 JSArray::cast(arg)->GetPrototype() != *array_proto) { | 1004 JSObject::cast(native_context->array_function()->prototype()); |
| 1011 AllowHeapAllocation allow_allocation; | 1005 if (!ArrayPrototypeHasNoElements(heap, native_context, array_proto)) { |
| 1012 return CallJsBuiltin(isolate, "ArrayConcat", args); | |
| 1013 } | |
| 1014 int len = Smi::cast(JSArray::cast(arg)->length())->value(); | |
| 1015 | |
| 1016 // We shouldn't overflow when adding another len. | |
| 1017 const int kHalfOfMaxInt = 1 << (kBitsPerInt - 2); | |
| 1018 STATIC_ASSERT(FixedArray::kMaxLength < kHalfOfMaxInt); | |
| 1019 USE(kHalfOfMaxInt); | |
| 1020 result_len += len; | |
| 1021 ASSERT(result_len >= 0); | |
| 1022 | |
| 1023 if (result_len > FixedDoubleArray::kMaxLength) { | |
| 1024 AllowHeapAllocation allow_allocation; | 1006 AllowHeapAllocation allow_allocation; |
| 1025 return CallJsBuiltin(isolate, "ArrayConcat", args); | 1007 return CallJsBuiltin(isolate, "ArrayConcat", args); |
| 1026 } | 1008 } |
| 1027 | 1009 |
| 1028 ElementsKind arg_kind = JSArray::cast(arg)->map()->elements_kind(); | 1010 // Iterate through all the arguments performing checks |
| 1029 has_double = has_double || IsFastDoubleElementsKind(arg_kind); | 1011 // and calculating total length. |
| 1030 is_holey = is_holey || IsFastHoleyElementsKind(arg_kind); | 1012 bool is_holey = false; |
| 1031 if (IsMoreGeneralElementsKindTransition(elements_kind, arg_kind)) { | 1013 for (int i = 0; i < n_arguments; i++) { |
| 1032 elements_kind = arg_kind; | 1014 Object* arg = args[i]; |
| 1015 if (!arg->IsJSArray() || |
| 1016 !JSArray::cast(arg)->HasFastElements() || |
| 1017 JSArray::cast(arg)->GetPrototype() != array_proto) { |
| 1018 AllowHeapAllocation allow_allocation; |
| 1019 return CallJsBuiltin(isolate, "ArrayConcat", args); |
| 1020 } |
| 1021 int len = Smi::cast(JSArray::cast(arg)->length())->value(); |
| 1022 |
| 1023 // We shouldn't overflow when adding another len. |
| 1024 const int kHalfOfMaxInt = 1 << (kBitsPerInt - 2); |
| 1025 STATIC_ASSERT(FixedArray::kMaxLength < kHalfOfMaxInt); |
| 1026 USE(kHalfOfMaxInt); |
| 1027 result_len += len; |
| 1028 ASSERT(result_len >= 0); |
| 1029 |
| 1030 if (result_len > FixedDoubleArray::kMaxLength) { |
| 1031 AllowHeapAllocation allow_allocation; |
| 1032 return CallJsBuiltin(isolate, "ArrayConcat", args); |
| 1033 } |
| 1034 |
| 1035 ElementsKind arg_kind = JSArray::cast(arg)->map()->elements_kind(); |
| 1036 has_double = has_double || IsFastDoubleElementsKind(arg_kind); |
| 1037 is_holey = is_holey || IsFastHoleyElementsKind(arg_kind); |
| 1038 if (IsMoreGeneralElementsKindTransition(elements_kind, arg_kind)) { |
| 1039 elements_kind = arg_kind; |
| 1040 } |
| 1033 } | 1041 } |
| 1042 if (is_holey) elements_kind = GetHoleyElementsKind(elements_kind); |
| 1034 } | 1043 } |
| 1035 | 1044 |
| 1036 if (is_holey) elements_kind = GetHoleyElementsKind(elements_kind); | |
| 1037 | |
| 1038 // If a double array is concatted into a fast elements array, the fast | 1045 // If a double array is concatted into a fast elements array, the fast |
| 1039 // elements array needs to be initialized to contain proper holes, since | 1046 // elements array needs to be initialized to contain proper holes, since |
| 1040 // boxing doubles may cause incremental marking. | 1047 // boxing doubles may cause incremental marking. |
| 1041 ArrayStorageAllocationMode mode = | 1048 ArrayStorageAllocationMode mode = |
| 1042 has_double && IsFastObjectElementsKind(elements_kind) | 1049 has_double && IsFastObjectElementsKind(elements_kind) |
| 1043 ? INITIALIZE_ARRAY_ELEMENTS_WITH_HOLE : DONT_INITIALIZE_ARRAY_ELEMENTS; | 1050 ? INITIALIZE_ARRAY_ELEMENTS_WITH_HOLE : DONT_INITIALIZE_ARRAY_ELEMENTS; |
| 1044 Handle<JSArray> result_array = | 1051 Handle<JSArray> result_array = |
| 1045 isolate->factory()->NewJSArray(elements_kind, | 1052 isolate->factory()->NewJSArray(elements_kind, |
| 1046 result_len, | 1053 result_len, |
| 1047 result_len, | 1054 result_len, |
| (...skipping 680 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1728 } | 1735 } |
| 1729 BUILTIN_LIST_C(DEFINE_BUILTIN_ACCESSOR_C) | 1736 BUILTIN_LIST_C(DEFINE_BUILTIN_ACCESSOR_C) |
| 1730 BUILTIN_LIST_A(DEFINE_BUILTIN_ACCESSOR_A) | 1737 BUILTIN_LIST_A(DEFINE_BUILTIN_ACCESSOR_A) |
| 1731 BUILTIN_LIST_H(DEFINE_BUILTIN_ACCESSOR_H) | 1738 BUILTIN_LIST_H(DEFINE_BUILTIN_ACCESSOR_H) |
| 1732 BUILTIN_LIST_DEBUG_A(DEFINE_BUILTIN_ACCESSOR_A) | 1739 BUILTIN_LIST_DEBUG_A(DEFINE_BUILTIN_ACCESSOR_A) |
| 1733 #undef DEFINE_BUILTIN_ACCESSOR_C | 1740 #undef DEFINE_BUILTIN_ACCESSOR_C |
| 1734 #undef DEFINE_BUILTIN_ACCESSOR_A | 1741 #undef DEFINE_BUILTIN_ACCESSOR_A |
| 1735 | 1742 |
| 1736 | 1743 |
| 1737 } } // namespace v8::internal | 1744 } } // namespace v8::internal |
| OLD | NEW |