| 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 |