Chromium Code Reviews| Index: src/builtins/builtins-typedarray.cc |
| diff --git a/src/builtins/builtins-typedarray.cc b/src/builtins/builtins-typedarray.cc |
| index 3a85c18620c5d8f20cbd567e30ba275a8734d23a..ef9716150b0ca4d6041af5cd79e869096bba536b 100644 |
| --- a/src/builtins/builtins-typedarray.cc |
| +++ b/src/builtins/builtins-typedarray.cc |
| @@ -41,6 +41,78 @@ int64_t CapRelativeIndex(Handle<Object> num, int64_t minimum, int64_t maximum) { |
| : std::min<int64_t>(relative, maximum); |
| } |
| +// ES7 section 22.2.4.6 TypedArrayCreate ( constructor, argumentList ) |
| +// Only for the case when argumentList is a list of a single number (size) |
| +MaybeHandle<JSTypedArray> TypedArrayCreate(Isolate* isolate, |
| + Handle<JSFunction> default_ctor, |
| + int64_t size, |
| + const char* method_name) { |
| + // 1. Let newTypedArray be ? Construct(constructor, argumentList). |
| + Handle<Object> new_obj; |
| + { |
| + const int argc = 1; |
| + ScopedVector<Handle<Object>> argv(argc); |
| + argv[0] = isolate->factory()->NewNumber(size); |
| + ASSIGN_RETURN_ON_EXCEPTION( |
| + isolate, new_obj, Execution::New((default_ctor), argc, argv.start()), |
| + JSTypedArray); |
| + } |
| + |
| + // 2. Perform ? ValidateTypedArray(newTypedArray). |
| + Handle<JSTypedArray> new_array; |
| + ASSIGN_RETURN_ON_EXCEPTION( |
| + isolate, new_array, JSTypedArray::Validate(isolate, new_obj, method_name), |
| + JSTypedArray); |
| + |
| + // 3. If newTypedArray.[[ArrayLength]] < size, throw a TypeError exception. |
| + if (new_array->length_value() < size) { |
| + const MessageTemplate::Template message = |
| + MessageTemplate::kTypedArrayTooShort; |
| + THROW_NEW_ERROR(isolate, NewTypeError(message), JSTypedArray); |
| + } |
| + |
| + // 4. Return newTypedArray. |
| + return new_array; |
| +} |
| + |
| +// ES7 section 22.2.4.7 TypedArraySpeciesCreate ( exemplar, argumentList ) |
| +// Only for the case when argumentList is a list of a single number (size) |
| +MaybeHandle<JSTypedArray> TypedArraySpeciesCreate(Isolate* isolate, |
| + Handle<JSTypedArray> exemplar, |
| + int64_t size, |
| + const char* method_name) { |
| + // 1. Assert: exemplar is an Object that has a [[TypedArrayName]] internal |
| + // slot. |
| + DCHECK(examplar->IsJSTypedArray()); |
| + |
| + // 2. Let defaultConstructor be the intrinsic object listed in column one of |
| + // Table 51 for exemplar.[[TypedArrayName]]. |
| + Handle<JSFunction> default_ctor = isolate->uint8_array_fun(); |
| + switch (exemplar->type()) { |
| +#define TYPED_ARRAY_CTOR(Type, type, TYPE, ctype, size) \ |
| + case kExternal##Type##Array: { \ |
| + default_ctor = isolate->type##_array_fun(); \ |
| + break; \ |
| + } |
| + |
| + TYPED_ARRAYS(TYPED_ARRAY_CTOR) |
| +#undef TYPED_ARRAY_CTOR |
| + default: |
| + UNREACHABLE(); |
| + } |
| + |
| + // 3. Let constructor be ? SpeciesConstructor(exemplar, defaultConstructor). |
| + Handle<Object> ctor; |
| + ASSIGN_RETURN_ON_EXCEPTION( |
| + isolate, ctor, |
| + Object::SpeciesConstructor(isolate, exemplar, default_ctor), |
| + JSTypedArray); |
| + |
| + // 4. Return ? TypedArrayCreate(constructor, argumentList). |
| + return TypedArrayCreate(isolate, Handle<JSFunction>::cast(ctor), size, |
| + method_name); |
| +} |
| + |
| } // namespace |
| BUILTIN(TypedArrayPrototypeCopyWithin) { |
| @@ -206,5 +278,73 @@ BUILTIN(TypedArrayPrototypeLastIndexOf) { |
| return *isolate->factory()->NewNumberFromInt64(result.FromJust()); |
| } |
| +BUILTIN(TypedArrayPrototypeSlice) { |
| + HandleScope scope(isolate); |
| + |
| + Handle<JSTypedArray> array; |
| + const char* method = "%TypedArray%.prototype.slice"; |
| + ASSIGN_RETURN_FAILURE_ON_EXCEPTION( |
| + isolate, array, JSTypedArray::Validate(isolate, args.receiver(), method)); |
| + |
| + int64_t len = array->length_value(); |
| + int64_t start = 0; |
| + int64_t end = len; |
| + { |
| + Handle<Object> num = args.atOrUndefined(isolate, 1); |
| + if (!num->IsUndefined(isolate)) { |
| + ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, num, |
| + Object::ToInteger(isolate, num)); |
| + start = CapRelativeIndex(num, 0, len); |
| + |
| + num = args.atOrUndefined(isolate, 2); |
| + if (!num->IsUndefined(isolate)) { |
| + ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, num, |
| + Object::ToInteger(isolate, num)); |
| + end = CapRelativeIndex(num, 0, len); |
| + } |
| + } |
| + } |
| + |
| + int64_t count = std::max<int64_t>(end - start, 0); |
| + |
| + Handle<JSTypedArray> result_array; |
| + ASSIGN_RETURN_FAILURE_ON_EXCEPTION( |
| + isolate, result_array, |
| + TypedArraySpeciesCreate(isolate, array, count, method)); |
| + |
| + // TODO(cwhan.tunz): neutering check of the result_array should be done in |
| + // TypedArraySpeciesCreate, but currently ValidateTypedArray does not throw |
| + // for neutered buffer, so this is a temporary neutering check for the result |
| + // array |
| + if (V8_UNLIKELY(result_array->WasNeutered())) return *result_array; |
| + |
| + // TODO(cwhan.tunz): should throw. |
| + if (V8_UNLIKELY(array->WasNeutered())) return *result_array; |
| + |
| + // Fast path for the same type result array |
| + if (result_array->type() == array->type()) { |
| + int64_t element_size = array->element_size(); |
| + |
| + Handle<FixedTypedArrayBase> src_elements( |
| + FixedTypedArrayBase::cast(array->elements())); |
| + Handle<FixedTypedArrayBase> result_elements( |
| + FixedTypedArrayBase::cast(result_array->elements())); |
|
Camillo Bruni
2017/03/20 13:37:25
nit: No need for handles here. Add "DisallowHeapAl
Choongwoo Han
2017/03/21 12:39:03
Done.
|
| + |
| + uint8_t* src = static_cast<uint8_t*>(src_elements->DataPtr()); |
| + uint8_t* result = static_cast<uint8_t*>(result_elements->DataPtr()); |
| + std::memcpy(result, src + start * element_size, count * element_size); |
| + return *result_array; |
| + } |
| + |
| + // If the types of the two typed arrays are different, take a slow path |
| + ElementsAccessor* source_accessor = array->GetElementsAccessor(); |
| + ElementsAccessor* result_accessor = result_array->GetElementsAccessor(); |
| + for (int64_t k = start; k < end; k++) { |
| + Handle<Object> elem = source_accessor->Get(array, k); |
| + result_accessor->Set(result_array, k, *elem); |
|
Camillo Bruni
2017/03/20 13:37:25
If you push this loop down into the elements acces
Choongwoo Han
2017/03/21 12:39:03
What is the meaning of one virtual call? also, I'm
|
| + } |
| + return *result_array; |
| +} |
| + |
| } // namespace internal |
| } // namespace v8 |