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