| // Copyright 2018 the V8 project authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include 'src/builtins/builtins-array-gen.h' |
| |
| namespace array { |
| // Naming convention from elements.cc. We have a similar intent but implement |
| // fastpaths using generics instead of using a class hierarchy for elements |
| // kinds specific implementations. |
| type GenericElementsAccessor extends ElementsKind; |
| type FastPackedSmiElements extends ElementsKind; |
| type FastPackedObjectElements extends ElementsKind; |
| type FastPackedDoubleElements extends ElementsKind; |
| type FastSmiOrObjectElements extends ElementsKind; |
| type FastDoubleElements extends ElementsKind; |
| type DictionaryElements extends ElementsKind; |
| |
| macro EnsureWriteableFastElements(implicit context: Context)(array: JSArray) { |
| assert(IsFastElementsKind(array.map.elements_kind)); |
| |
| const elements: FixedArrayBase = array.elements; |
| if (elements.map != kCOWMap) return; |
| |
| // There are no COW *_DOUBLE_ELEMENTS arrays, so we are allowed to always |
| // extract FixedArrays and don't have to worry about FixedDoubleArrays. |
| assert(IsFastSmiOrTaggedElementsKind(array.map.elements_kind)); |
| |
| const length = Convert<intptr>(Cast<Smi>(array.length) otherwise unreachable); |
| array.elements = |
| ExtractFixedArray(UnsafeCast<FixedArray>(elements), 0, length, length); |
| assert(array.elements.map != kCOWMap); |
| } |
| |
| macro LoadElementOrUndefined(implicit context: Context)( |
| a: FixedArray, i: Smi): JSAny { |
| const e = UnsafeCast<(JSAny | TheHole)>(a.objects[i]); |
| return ReplaceTheHoleWithUndefined(e); |
| } |
| |
| macro LoadElementOrUndefined(a: FixedDoubleArray, i: Smi): NumberOrUndefined { |
| const f: float64 = a.floats[i].Value() otherwise return Undefined; |
| return AllocateHeapNumberWithValue(f); |
| } |
| |
| macro StoreArrayHole(elements: FixedDoubleArray, k: Smi): void { |
| elements.floats[k] = kDoubleHole; |
| } |
| |
| macro StoreArrayHole(elements: FixedArray, k: Smi): void { |
| elements.objects[k] = TheHole; |
| } |
| |
| extern macro SetPropertyLength(implicit context: Context)(JSAny, Number); |
| |
| const kLengthDescriptorIndex: |
| constexpr int31 generates 'JSArray::kLengthDescriptorIndex'; |
| const kAttributesReadOnlyMask: constexpr int31 |
| generates 'PropertyDetails::kAttributesReadOnlyMask'; |
| |
| @export |
| macro EnsureArrayLengthWritable(implicit context: Context)(map: Map): |
| void labels Bailout { |
| // Don't support arrays in dictionary named property mode. |
| if (IsDictionaryMap(map)) { |
| goto Bailout; |
| } |
| |
| // Check whether the length property is writable. The length property is the |
| // only default named property on arrays. It's nonconfigurable, hence is |
| // guaranteed to stay the first property. |
| const descriptors: DescriptorArray = map.instance_descriptors; |
| const descriptor:&DescriptorEntry = |
| &descriptors.descriptors[kLengthDescriptorIndex]; |
| assert(TaggedEqual(descriptor->key, LengthStringConstant())); |
| const details: Smi = UnsafeCast<Smi>(descriptor->details); |
| if ((details & kAttributesReadOnlyMask) != 0) { |
| goto Bailout; |
| } |
| } |
| |
| macro CreateJSArrayWithElements(implicit context: Context)(array: FixedArray): |
| JSArray { |
| const nativeContext: NativeContext = LoadNativeContext(context); |
| const map: Map = |
| LoadJSArrayElementsMap(ElementsKind::PACKED_ELEMENTS, nativeContext); |
| return AllocateJSArray(map, array, array.length); |
| } |
| } |