// Copyright 2020 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/heap/factory-base.h" #include "src/ast/ast-source-ranges.h" #include "src/ast/ast.h" #include "src/common/assert-scope.h" #include "src/execution/local-isolate.h" #include "src/handles/handles-inl.h" #include "src/heap/factory.h" #include "src/heap/heap-inl.h" #include "src/heap/local-factory-inl.h" #include "src/heap/memory-chunk.h" #include "src/heap/read-only-heap.h" #include "src/logging/local-logger.h" #include "src/logging/log.h" #include "src/objects/instance-type.h" #include "src/objects/literal-objects-inl.h" #include "src/objects/module-inl.h" #include "src/objects/oddball.h" #include "src/objects/shared-function-info-inl.h" #include "src/objects/shared-function-info.h" #include "src/objects/source-text-module.h" #include "src/objects/string-inl.h" #include "src/objects/string.h" #include "src/objects/swiss-name-dictionary-inl.h" #include "src/objects/template-objects-inl.h" namespace v8 { namespace internal { template template Handle FactoryBase::NewHeapNumber() { STATIC_ASSERT(HeapNumber::kSize <= kMaxRegularHeapObjectSize); Map map = read_only_roots().heap_number_map(); HeapObject result = AllocateRawWithImmortalMap(HeapNumber::kSize, allocation, map, kDoubleUnaligned); return handle(HeapNumber::cast(result), isolate()); } template V8_EXPORT_PRIVATE Handle FactoryBase::NewHeapNumber(); template V8_EXPORT_PRIVATE Handle FactoryBase::NewHeapNumber(); template V8_EXPORT_PRIVATE Handle FactoryBase::NewHeapNumber(); template V8_EXPORT_PRIVATE Handle FactoryBase::NewHeapNumber(); template V8_EXPORT_PRIVATE Handle FactoryBase::NewHeapNumber(); template Handle FactoryBase::NewStruct(InstanceType type, AllocationType allocation) { ReadOnlyRoots roots = read_only_roots(); Map map = Map::GetInstanceTypeMap(roots, type); int size = map.instance_size(); return handle(NewStructInternal(roots, map, size, allocation), isolate()); } template Handle FactoryBase::NewAccessorPair() { auto accessors = NewStructInternal(ACCESSOR_PAIR_TYPE, AllocationType::kOld); DisallowGarbageCollection no_gc; accessors.set_getter(read_only_roots().null_value(), SKIP_WRITE_BARRIER); accessors.set_setter(read_only_roots().null_value(), SKIP_WRITE_BARRIER); return handle(accessors, isolate()); } template Handle FactoryBase::NewCodeDataContainer( int flags, AllocationType allocation) { Map map = read_only_roots().code_data_container_map(); int size = map.instance_size(); CodeDataContainer data_container = CodeDataContainer::cast( AllocateRawWithImmortalMap(size, allocation, map)); DisallowGarbageCollection no_gc; data_container.set_next_code_link(read_only_roots().undefined_value(), SKIP_WRITE_BARRIER); data_container.set_kind_specific_flags(flags, kRelaxedStore); if (V8_EXTERNAL_CODE_SPACE_BOOL) { data_container.set_code_cage_base(impl()->isolate()->code_cage_base(), kRelaxedStore); Isolate* isolate_for_sandbox = impl()->isolate_for_sandbox(); data_container.AllocateExternalPointerEntries(isolate_for_sandbox); data_container.set_raw_code(Smi::zero(), SKIP_WRITE_BARRIER); data_container.set_code_entry_point(isolate_for_sandbox, kNullAddress); } data_container.clear_padding(); return handle(data_container, isolate()); } template Handle FactoryBase::NewFixedArray(int length, AllocationType allocation) { if (length == 0) return impl()->empty_fixed_array(); if (length < 0 || length > FixedArray::kMaxLength) { FATAL("Fatal JavaScript invalid size error %d", length); UNREACHABLE(); } return NewFixedArrayWithFiller( read_only_roots().fixed_array_map_handle(), length, read_only_roots().undefined_value_handle(), allocation); } template Handle FactoryBase::NewFixedArrayWithMap( Handle map, int length, AllocationType allocation) { // Zero-length case must be handled outside, where the knowledge about // the map is. DCHECK_LT(0, length); return NewFixedArrayWithFiller( map, length, read_only_roots().undefined_value_handle(), allocation); } template Handle FactoryBase::NewFixedArrayWithHoles( int length, AllocationType allocation) { DCHECK_LE(0, length); if (length == 0) return impl()->empty_fixed_array(); return NewFixedArrayWithFiller( read_only_roots().fixed_array_map_handle(), length, read_only_roots().the_hole_value_handle(), allocation); } template Handle FactoryBase::NewFixedArrayWithFiller( Handle map, int length, Handle filler, AllocationType allocation) { HeapObject result = AllocateRawFixedArray(length, allocation); DisallowGarbageCollection no_gc; DCHECK(ReadOnlyHeap::Contains(*map)); DCHECK(ReadOnlyHeap::Contains(*filler)); result.set_map_after_allocation(*map, SKIP_WRITE_BARRIER); FixedArray array = FixedArray::cast(result); array.set_length(length); MemsetTagged(array.data_start(), *filler, length); return handle(array, isolate()); } template Handle FactoryBase::NewFixedArrayWithZeroes( int length, AllocationType allocation) { DCHECK_LE(0, length); if (length == 0) return impl()->empty_fixed_array(); if (length > FixedArray::kMaxLength) { FATAL("Invalid FixedArray size %d", length); } HeapObject result = AllocateRawFixedArray(length, allocation); DisallowGarbageCollection no_gc; result.set_map_after_allocation(read_only_roots().fixed_array_map(), SKIP_WRITE_BARRIER); FixedArray array = FixedArray::cast(result); array.set_length(length); MemsetTagged(array.data_start(), Smi::zero(), length); return handle(array, isolate()); } template Handle FactoryBase::NewFixedDoubleArray( int length, AllocationType allocation) { if (length == 0) return impl()->empty_fixed_array(); if (length < 0 || length > FixedDoubleArray::kMaxLength) { FATAL("Fatal JavaScript invalid size error %d", length); UNREACHABLE(); } int size = FixedDoubleArray::SizeFor(length); Map map = read_only_roots().fixed_double_array_map(); HeapObject result = AllocateRawWithImmortalMap(size, allocation, map, kDoubleAligned); DisallowGarbageCollection no_gc; FixedDoubleArray array = FixedDoubleArray::cast(result); array.set_length(length); return handle(array, isolate()); } template Handle FactoryBase::NewWeakFixedArrayWithMap( Map map, int length, AllocationType allocation) { // Zero-length case must be handled outside. DCHECK_LT(0, length); DCHECK(ReadOnlyHeap::Contains(map)); HeapObject result = AllocateRawArray(WeakFixedArray::SizeFor(length), allocation); result.set_map_after_allocation(map, SKIP_WRITE_BARRIER); DisallowGarbageCollection no_gc; WeakFixedArray array = WeakFixedArray::cast(result); array.set_length(length); MemsetTagged(ObjectSlot(array.data_start()), read_only_roots().undefined_value(), length); return handle(array, isolate()); } template Handle FactoryBase::NewWeakFixedArray( int length, AllocationType allocation) { DCHECK_LE(0, length); if (length == 0) return impl()->empty_weak_fixed_array(); return NewWeakFixedArrayWithMap(read_only_roots().weak_fixed_array_map(), length, allocation); } template Handle FactoryBase::NewByteArray(int length, AllocationType allocation) { if (length < 0 || length > ByteArray::kMaxLength) { FATAL("Fatal JavaScript invalid size error %d", length); UNREACHABLE(); } if (length == 0) return impl()->empty_byte_array(); int size = ByteArray::SizeFor(length); HeapObject result = AllocateRawWithImmortalMap( size, allocation, read_only_roots().byte_array_map()); DisallowGarbageCollection no_gc; ByteArray array = ByteArray::cast(result); array.set_length(length); array.clear_padding(); return handle(array, isolate()); } template Handle FactoryBase::NewBytecodeArray( int length, const byte* raw_bytecodes, int frame_size, int parameter_count, Handle constant_pool) { if (length < 0 || length > BytecodeArray::kMaxLength) { FATAL("Fatal JavaScript invalid size error %d", length); UNREACHABLE(); } // Bytecode array is AllocationType::kOld, so constant pool array should be // too. DCHECK(!Heap::InYoungGeneration(*constant_pool)); int size = BytecodeArray::SizeFor(length); HeapObject result = AllocateRawWithImmortalMap( size, AllocationType::kOld, read_only_roots().bytecode_array_map()); DisallowGarbageCollection no_gc; BytecodeArray instance = BytecodeArray::cast(result); instance.set_length(length); instance.set_frame_size(frame_size); instance.set_parameter_count(parameter_count); instance.set_incoming_new_target_or_generator_register( interpreter::Register::invalid_value()); instance.reset_osr_urgency_and_install_target(); instance.set_bytecode_age(BytecodeArray::kNoAgeBytecodeAge); instance.set_constant_pool(*constant_pool); instance.set_handler_table(read_only_roots().empty_byte_array(), SKIP_WRITE_BARRIER); instance.set_source_position_table(read_only_roots().undefined_value(), kReleaseStore, SKIP_WRITE_BARRIER); CopyBytes(reinterpret_cast(instance.GetFirstBytecodeAddress()), raw_bytecodes, length); instance.clear_padding(); return handle(instance, isolate()); } template Handle