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 1021 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1032 | 1032 |
1033 void CollectElementIndices(Handle<JSObject> object, uint32_t range, | 1033 void CollectElementIndices(Handle<JSObject> object, uint32_t range, |
1034 List<uint32_t>* indices) { | 1034 List<uint32_t>* indices) { |
1035 Isolate* isolate = object->GetIsolate(); | 1035 Isolate* isolate = object->GetIsolate(); |
1036 ElementsKind kind = object->GetElementsKind(); | 1036 ElementsKind kind = object->GetElementsKind(); |
1037 switch (kind) { | 1037 switch (kind) { |
1038 case FAST_SMI_ELEMENTS: | 1038 case FAST_SMI_ELEMENTS: |
1039 case FAST_ELEMENTS: | 1039 case FAST_ELEMENTS: |
1040 case FAST_HOLEY_SMI_ELEMENTS: | 1040 case FAST_HOLEY_SMI_ELEMENTS: |
1041 case FAST_HOLEY_ELEMENTS: { | 1041 case FAST_HOLEY_ELEMENTS: { |
1042 Handle<FixedArray> elements(FixedArray::cast(object->elements())); | 1042 DisallowHeapAllocation no_gc; |
| 1043 FixedArray* elements = FixedArray::cast(object->elements()); |
1043 uint32_t length = static_cast<uint32_t>(elements->length()); | 1044 uint32_t length = static_cast<uint32_t>(elements->length()); |
1044 if (range < length) length = range; | 1045 if (range < length) length = range; |
1045 for (uint32_t i = 0; i < length; i++) { | 1046 for (uint32_t i = 0; i < length; i++) { |
1046 if (!elements->get(i)->IsTheHole()) { | 1047 if (!elements->get(i)->IsTheHole()) { |
1047 indices->Add(i); | 1048 indices->Add(i); |
1048 } | 1049 } |
1049 } | 1050 } |
1050 break; | 1051 break; |
1051 } | 1052 } |
1052 case FAST_HOLEY_DOUBLE_ELEMENTS: | 1053 case FAST_HOLEY_DOUBLE_ELEMENTS: |
1053 case FAST_DOUBLE_ELEMENTS: { | 1054 case FAST_DOUBLE_ELEMENTS: { |
1054 if (object->elements()->IsFixedArray()) { | 1055 if (object->elements()->IsFixedArray()) { |
1055 DCHECK(object->elements()->length() == 0); | 1056 DCHECK(object->elements()->length() == 0); |
1056 break; | 1057 break; |
1057 } | 1058 } |
1058 Handle<FixedDoubleArray> elements( | 1059 Handle<FixedDoubleArray> elements( |
1059 FixedDoubleArray::cast(object->elements())); | 1060 FixedDoubleArray::cast(object->elements())); |
1060 uint32_t length = static_cast<uint32_t>(elements->length()); | 1061 uint32_t length = static_cast<uint32_t>(elements->length()); |
1061 if (range < length) length = range; | 1062 if (range < length) length = range; |
1062 for (uint32_t i = 0; i < length; i++) { | 1063 for (uint32_t i = 0; i < length; i++) { |
1063 if (!elements->is_the_hole(i)) { | 1064 if (!elements->is_the_hole(i)) { |
1064 indices->Add(i); | 1065 indices->Add(i); |
1065 } | 1066 } |
1066 } | 1067 } |
1067 break; | 1068 break; |
1068 } | 1069 } |
1069 case DICTIONARY_ELEMENTS: { | 1070 case DICTIONARY_ELEMENTS: { |
1070 Handle<SeededNumberDictionary> dict( | 1071 DisallowHeapAllocation no_gc; |
1071 SeededNumberDictionary::cast(object->elements())); | 1072 SeededNumberDictionary* dict = |
| 1073 SeededNumberDictionary::cast(object->elements()); |
1072 uint32_t capacity = dict->Capacity(); | 1074 uint32_t capacity = dict->Capacity(); |
| 1075 Heap* heap = isolate->heap(); |
| 1076 Object* undefined = heap->undefined_value(); |
| 1077 Object* the_hole = heap->the_hole_value(); |
1073 FOR_WITH_HANDLE_SCOPE(isolate, uint32_t, j = 0, j, j < capacity, j++, { | 1078 FOR_WITH_HANDLE_SCOPE(isolate, uint32_t, j = 0, j, j < capacity, j++, { |
1074 Handle<Object> k(dict->KeyAt(j), isolate); | 1079 Object* k = dict->KeyAt(j); |
1075 if (dict->IsKey(*k)) { | 1080 if (k == undefined) continue; |
1076 DCHECK(k->IsNumber()); | 1081 if (k == the_hole) continue; |
1077 uint32_t index = static_cast<uint32_t>(k->Number()); | 1082 DCHECK(k->IsNumber()); |
1078 if (index < range) { | 1083 uint32_t index = static_cast<uint32_t>(k->Number()); |
1079 indices->Add(index); | 1084 if (index < range) { |
1080 } | 1085 indices->Add(index); |
1081 } | 1086 } |
1082 }); | 1087 }); |
1083 break; | 1088 break; |
1084 } | 1089 } |
1085 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) case TYPE##_ELEMENTS: | 1090 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) case TYPE##_ELEMENTS: |
1086 | 1091 |
1087 TYPED_ARRAYS(TYPED_ARRAY_CASE) | 1092 TYPED_ARRAYS(TYPED_ARRAY_CASE) |
1088 #undef TYPED_ARRAY_CASE | 1093 #undef TYPED_ARRAY_CASE |
1089 { | 1094 { |
1090 uint32_t length = static_cast<uint32_t>( | 1095 uint32_t length = static_cast<uint32_t>( |
(...skipping 312 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1403 Handle<FixedDoubleArray>::cast(storage); | 1408 Handle<FixedDoubleArray>::cast(storage); |
1404 for (int i = 0; i < argument_count; i++) { | 1409 for (int i = 0; i < argument_count; i++) { |
1405 Handle<Object> obj((*args)[i], isolate); | 1410 Handle<Object> obj((*args)[i], isolate); |
1406 if (obj->IsSmi()) { | 1411 if (obj->IsSmi()) { |
1407 double_storage->set(j, Smi::cast(*obj)->value()); | 1412 double_storage->set(j, Smi::cast(*obj)->value()); |
1408 j++; | 1413 j++; |
1409 } else if (obj->IsNumber()) { | 1414 } else if (obj->IsNumber()) { |
1410 double_storage->set(j, obj->Number()); | 1415 double_storage->set(j, obj->Number()); |
1411 j++; | 1416 j++; |
1412 } else { | 1417 } else { |
| 1418 DisallowHeapAllocation no_gc; |
1413 JSArray* array = JSArray::cast(*obj); | 1419 JSArray* array = JSArray::cast(*obj); |
1414 uint32_t length = static_cast<uint32_t>(array->length()->Number()); | 1420 uint32_t length = static_cast<uint32_t>(array->length()->Number()); |
1415 switch (array->GetElementsKind()) { | 1421 switch (array->GetElementsKind()) { |
1416 case FAST_HOLEY_DOUBLE_ELEMENTS: | 1422 case FAST_HOLEY_DOUBLE_ELEMENTS: |
1417 case FAST_DOUBLE_ELEMENTS: { | 1423 case FAST_DOUBLE_ELEMENTS: { |
1418 // Empty array is FixedArray but not FixedDoubleArray. | 1424 // Empty array is FixedArray but not FixedDoubleArray. |
1419 if (length == 0) break; | 1425 if (length == 0) break; |
1420 FixedDoubleArray* elements = | 1426 FixedDoubleArray* elements = |
1421 FixedDoubleArray::cast(array->elements()); | 1427 FixedDoubleArray::cast(array->elements()); |
1422 for (uint32_t i = 0; i < length; i++) { | 1428 for (uint32_t i = 0; i < length; i++) { |
1423 if (elements->is_the_hole(i)) { | 1429 if (elements->is_the_hole(i)) { |
1424 // TODO(jkummerow/verwaest): We could be a bit more clever | 1430 // TODO(jkummerow/verwaest): We could be a bit more clever |
1425 // here: Check if there are no elements/getters on the | 1431 // here: Check if there are no elements/getters on the |
1426 // prototype chain, and if so, allow creation of a holey | 1432 // prototype chain, and if so, allow creation of a holey |
1427 // result array. | 1433 // result array. |
1428 // Same thing below (holey smi case). | 1434 // Same thing below (holey smi case). |
1429 failure = true; | 1435 failure = true; |
1430 break; | 1436 break; |
1431 } | 1437 } |
1432 double double_value = elements->get_scalar(i); | 1438 double double_value = elements->get_scalar(i); |
1433 double_storage->set(j, double_value); | 1439 double_storage->set(j, double_value); |
1434 j++; | 1440 j++; |
1435 } | 1441 } |
1436 break; | 1442 break; |
1437 } | 1443 } |
1438 case FAST_HOLEY_SMI_ELEMENTS: | 1444 case FAST_HOLEY_SMI_ELEMENTS: |
1439 case FAST_SMI_ELEMENTS: { | 1445 case FAST_SMI_ELEMENTS: { |
| 1446 Object* the_hole = isolate->heap()->the_hole_value(); |
1440 FixedArray* elements(FixedArray::cast(array->elements())); | 1447 FixedArray* elements(FixedArray::cast(array->elements())); |
1441 for (uint32_t i = 0; i < length; i++) { | 1448 for (uint32_t i = 0; i < length; i++) { |
1442 Object* element = elements->get(i); | 1449 Object* element = elements->get(i); |
1443 if (element->IsTheHole()) { | 1450 if (element == the_hole) { |
1444 failure = true; | 1451 failure = true; |
1445 break; | 1452 break; |
1446 } | 1453 } |
1447 int32_t int_value = Smi::cast(element)->value(); | 1454 int32_t int_value = Smi::cast(element)->value(); |
1448 double_storage->set(j, int_value); | 1455 double_storage->set(j, int_value); |
1449 j++; | 1456 j++; |
1450 } | 1457 } |
1451 break; | 1458 break; |
1452 } | 1459 } |
1453 case FAST_HOLEY_ELEMENTS: | 1460 case FAST_HOLEY_ELEMENTS: |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1523 MaybeHandle<JSArray> Fast_ArrayConcat(Isolate* isolate, Arguments* args) { | 1530 MaybeHandle<JSArray> Fast_ArrayConcat(Isolate* isolate, Arguments* args) { |
1524 int n_arguments = args->length(); | 1531 int n_arguments = args->length(); |
1525 int result_len = 0; | 1532 int result_len = 0; |
1526 { | 1533 { |
1527 DisallowHeapAllocation no_gc; | 1534 DisallowHeapAllocation no_gc; |
1528 // Iterate through all the arguments performing checks | 1535 // Iterate through all the arguments performing checks |
1529 // and calculating total length. | 1536 // and calculating total length. |
1530 for (int i = 0; i < n_arguments; i++) { | 1537 for (int i = 0; i < n_arguments; i++) { |
1531 Object* arg = (*args)[i]; | 1538 Object* arg = (*args)[i]; |
1532 if (!arg->IsJSArray()) return MaybeHandle<JSArray>(); | 1539 if (!arg->IsJSArray()) return MaybeHandle<JSArray>(); |
| 1540 if (!JSObject::cast(arg)->HasFastElements()) { |
| 1541 return MaybeHandle<JSArray>(); |
| 1542 } |
1533 if (!HasOnlySimpleReceiverElements(isolate, JSObject::cast(arg))) { | 1543 if (!HasOnlySimpleReceiverElements(isolate, JSObject::cast(arg))) { |
1534 return MaybeHandle<JSArray>(); | 1544 return MaybeHandle<JSArray>(); |
1535 } | 1545 } |
1536 // TODO(cbruni): support fast concatenation of DICTIONARY_ELEMENTS. | |
1537 if (!JSObject::cast(arg)->HasFastElements()) { | |
1538 return MaybeHandle<JSArray>(); | |
1539 } | |
1540 Handle<JSArray> array(JSArray::cast(arg), isolate); | 1546 Handle<JSArray> array(JSArray::cast(arg), isolate); |
1541 if (HasConcatSpreadableModifier(isolate, array)) { | 1547 if (HasConcatSpreadableModifier(isolate, array)) { |
1542 return MaybeHandle<JSArray>(); | 1548 return MaybeHandle<JSArray>(); |
1543 } | 1549 } |
1544 int len = Smi::cast(array->length())->value(); | 1550 int len = Smi::cast(array->length())->value(); |
1545 | 1551 |
1546 // We shouldn't overflow when adding another len. | 1552 // We shouldn't overflow when adding another len. |
1547 const int kHalfOfMaxInt = 1 << (kBitsPerInt - 2); | 1553 const int kHalfOfMaxInt = 1 << (kBitsPerInt - 2); |
1548 STATIC_ASSERT(FixedArray::kMaxLength < kHalfOfMaxInt); | 1554 STATIC_ASSERT(FixedArray::kMaxLength < kHalfOfMaxInt); |
1549 USE(kHalfOfMaxInt); | 1555 USE(kHalfOfMaxInt); |
(...skipping 3217 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4767 BUILTIN_LIST_T(DEFINE_BUILTIN_ACCESSOR_T) | 4773 BUILTIN_LIST_T(DEFINE_BUILTIN_ACCESSOR_T) |
4768 BUILTIN_LIST_H(DEFINE_BUILTIN_ACCESSOR_H) | 4774 BUILTIN_LIST_H(DEFINE_BUILTIN_ACCESSOR_H) |
4769 BUILTIN_LIST_DEBUG_A(DEFINE_BUILTIN_ACCESSOR_A) | 4775 BUILTIN_LIST_DEBUG_A(DEFINE_BUILTIN_ACCESSOR_A) |
4770 #undef DEFINE_BUILTIN_ACCESSOR_C | 4776 #undef DEFINE_BUILTIN_ACCESSOR_C |
4771 #undef DEFINE_BUILTIN_ACCESSOR_A | 4777 #undef DEFINE_BUILTIN_ACCESSOR_A |
4772 #undef DEFINE_BUILTIN_ACCESSOR_T | 4778 #undef DEFINE_BUILTIN_ACCESSOR_T |
4773 #undef DEFINE_BUILTIN_ACCESSOR_H | 4779 #undef DEFINE_BUILTIN_ACCESSOR_H |
4774 | 4780 |
4775 } // namespace internal | 4781 } // namespace internal |
4776 } // namespace v8 | 4782 } // namespace v8 |
OLD | NEW |