1 // Copyright 2020 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "src/heap/factory-base.h"
6
7 #include "src/ast/ast-source-ranges.h"
8 #include "src/ast/ast.h"
9 #include "src/common/assert-scope.h"
10 #include "src/execution/local-isolate.h"
11 #include "src/handles/handles-inl.h"
12 #include "src/heap/factory.h"
13 #include "src/heap/heap-inl.h"
14 #include "src/heap/local-factory-inl.h"
15 #include "src/heap/memory-chunk.h"
16 #include "src/heap/read-only-heap.h"
17 #include "src/logging/local-logger.h"
18 #include "src/logging/log.h"
19 #include "src/objects/instance-type.h"
20 #include "src/objects/literal-objects-inl.h"
21 #include "src/objects/module-inl.h"
22 #include "src/objects/oddball.h"
23 #include "src/objects/shared-function-info-inl.h"
24 #include "src/objects/shared-function-info.h"
25 #include "src/objects/source-text-module.h"
26 #include "src/objects/string-inl.h"
27 #include "src/objects/string.h"
28 #include "src/objects/swiss-name-dictionary-inl.h"
29 #include "src/objects/template-objects-inl.h"
30
31 namespace v8 {
32 namespace internal {
33
34 template <typename Impl>
35 template <AllocationType allocation>
NewHeapNumber()36 Handle<HeapNumber> FactoryBase<Impl>::NewHeapNumber() {
37 STATIC_ASSERT(HeapNumber::kSize <= kMaxRegularHeapObjectSize);
38 Map map = read_only_roots().heap_number_map();
39 HeapObject result = AllocateRawWithImmortalMap(HeapNumber::kSize, allocation,
40 map, kDoubleUnaligned);
41 return handle(HeapNumber::cast(result), isolate());
42 }
43
44 template V8_EXPORT_PRIVATE Handle<HeapNumber>
45 FactoryBase<Factory>::NewHeapNumber<AllocationType::kYoung>();
46 template V8_EXPORT_PRIVATE Handle<HeapNumber>
47 FactoryBase<Factory>::NewHeapNumber<AllocationType::kOld>();
48 template V8_EXPORT_PRIVATE Handle<HeapNumber>
49 FactoryBase<Factory>::NewHeapNumber<AllocationType::kReadOnly>();
50 template V8_EXPORT_PRIVATE Handle<HeapNumber>
51 FactoryBase<Factory>::NewHeapNumber<AllocationType::kSharedOld>();
52
53 template V8_EXPORT_PRIVATE Handle<HeapNumber>
54 FactoryBase<LocalFactory>::NewHeapNumber<AllocationType::kOld>();
55
56 template <typename Impl>
NewStruct(InstanceType type,AllocationType allocation)57 Handle<Struct> FactoryBase<Impl>::NewStruct(InstanceType type,
58 AllocationType allocation) {
59 ReadOnlyRoots roots = read_only_roots();
60 Map map = Map::GetInstanceTypeMap(roots, type);
61 int size = map.instance_size();
62 return handle(NewStructInternal(roots, map, size, allocation), isolate());
63 }
64
65 template <typename Impl>
NewAccessorPair()66 Handle<AccessorPair> FactoryBase<Impl>::NewAccessorPair() {
67 auto accessors =
68 NewStructInternal<AccessorPair>(ACCESSOR_PAIR_TYPE, AllocationType::kOld);
69 DisallowGarbageCollection no_gc;
70 accessors.set_getter(read_only_roots().null_value(), SKIP_WRITE_BARRIER);
71 accessors.set_setter(read_only_roots().null_value(), SKIP_WRITE_BARRIER);
72 return handle(accessors, isolate());
73 }
74
75 template <typename Impl>
NewCodeDataContainer(int flags,AllocationType allocation)76 Handle<CodeDataContainer> FactoryBase<Impl>::NewCodeDataContainer(
77 int flags, AllocationType allocation) {
78 Map map = read_only_roots().code_data_container_map();
79 int size = map.instance_size();
80 CodeDataContainer data_container = CodeDataContainer::cast(
81 AllocateRawWithImmortalMap(size, allocation, map));
82 DisallowGarbageCollection no_gc;
83 data_container.set_next_code_link(read_only_roots().undefined_value(),
84 SKIP_WRITE_BARRIER);
85 data_container.set_kind_specific_flags(flags, kRelaxedStore);
86 if (V8_EXTERNAL_CODE_SPACE_BOOL) {
87 data_container.set_code_cage_base(impl()->isolate()->code_cage_base(),
88 kRelaxedStore);
89 Isolate* isolate_for_sandbox = impl()->isolate_for_sandbox();
90 data_container.AllocateExternalPointerEntries(isolate_for_sandbox);
91 data_container.set_raw_code(Smi::zero(), SKIP_WRITE_BARRIER);
92 data_container.set_code_entry_point(isolate_for_sandbox, kNullAddress);
93 }
94 data_container.clear_padding();
95 return handle(data_container, isolate());
96 }
97
98 template <typename Impl>
NewFixedArray(int length,AllocationType allocation)99 Handle<FixedArray> FactoryBase<Impl>::NewFixedArray(int length,
100 AllocationType allocation) {
101 if (length == 0) return impl()->empty_fixed_array();
102 if (length < 0 || length > FixedArray::kMaxLength) {
103 FATAL("Fatal JavaScript invalid size error %d", length);
104 UNREACHABLE();
105 }
106 return NewFixedArrayWithFiller(
107 read_only_roots().fixed_array_map_handle(), length,
108 read_only_roots().undefined_value_handle(), allocation);
109 }
110
111 template <typename Impl>
NewFixedArrayWithMap(Handle<Map> map,int length,AllocationType allocation)112 Handle<FixedArray> FactoryBase<Impl>::NewFixedArrayWithMap(
113 Handle<Map> map, int length, AllocationType allocation) {
114 // Zero-length case must be handled outside, where the knowledge about
115 // the map is.
116 DCHECK_LT(0, length);
117 return NewFixedArrayWithFiller(
118 map, length, read_only_roots().undefined_value_handle(), allocation);
119 }
120
121 template <typename Impl>
NewFixedArrayWithHoles(int length,AllocationType allocation)122 Handle<FixedArray> FactoryBase<Impl>::NewFixedArrayWithHoles(
123 int length, AllocationType allocation) {
124 DCHECK_LE(0, length);
125 if (length == 0) return impl()->empty_fixed_array();
126 return NewFixedArrayWithFiller(
127 read_only_roots().fixed_array_map_handle(), length,
128 read_only_roots().the_hole_value_handle(), allocation);
129 }
130
131 template <typename Impl>
NewFixedArrayWithFiller(Handle<Map> map,int length,Handle<Oddball> filler,AllocationType allocation)132 Handle<FixedArray> FactoryBase<Impl>::NewFixedArrayWithFiller(
133 Handle<Map> map, int length, Handle<Oddball> filler,
134 AllocationType allocation) {
135 HeapObject result = AllocateRawFixedArray(length, allocation);
136 DisallowGarbageCollection no_gc;
137 DCHECK(ReadOnlyHeap::Contains(*map));
138 DCHECK(ReadOnlyHeap::Contains(*filler));
139 result.set_map_after_allocation(*map, SKIP_WRITE_BARRIER);
140 FixedArray array = FixedArray::cast(result);
141 array.set_length(length);
142 MemsetTagged(array.data_start(), *filler, length);
143 return handle(array, isolate());
144 }
145
146 template <typename Impl>
NewFixedArrayWithZeroes(int length,AllocationType allocation)147 Handle<FixedArray> FactoryBase<Impl>::NewFixedArrayWithZeroes(
148 int length, AllocationType allocation) {
149 DCHECK_LE(0, length);
150 if (length == 0) return impl()->empty_fixed_array();
151 if (length > FixedArray::kMaxLength) {
152 FATAL("Invalid FixedArray size %d", length);
153 }
154 HeapObject result = AllocateRawFixedArray(length, allocation);
155 DisallowGarbageCollection no_gc;
156 result.set_map_after_allocation(read_only_roots().fixed_array_map(),
157 SKIP_WRITE_BARRIER);
158 FixedArray array = FixedArray::cast(result);
159 array.set_length(length);
160 MemsetTagged(array.data_start(), Smi::zero(), length);
161 return handle(array, isolate());
162 }
163
164 template <typename Impl>
NewFixedDoubleArray(int length,AllocationType allocation)165 Handle<FixedArrayBase> FactoryBase<Impl>::NewFixedDoubleArray(
166 int length, AllocationType allocation) {
167 if (length == 0) return impl()->empty_fixed_array();
168 if (length < 0 || length > FixedDoubleArray::kMaxLength) {
169 FATAL("Fatal JavaScript invalid size error %d", length);
170 UNREACHABLE();
171 }
172 int size = FixedDoubleArray::SizeFor(length);
173 Map map = read_only_roots().fixed_double_array_map();
174 HeapObject result =
175 AllocateRawWithImmortalMap(size, allocation, map, kDoubleAligned);
176 DisallowGarbageCollection no_gc;
177 FixedDoubleArray array = FixedDoubleArray::cast(result);
178 array.set_length(length);
179 return handle(array, isolate());
180 }
181
182 template <typename Impl>
NewWeakFixedArrayWithMap(Map map,int length,AllocationType allocation)183 Handle<WeakFixedArray> FactoryBase<Impl>::NewWeakFixedArrayWithMap(
184 Map map, int length, AllocationType allocation) {
185 // Zero-length case must be handled outside.
186 DCHECK_LT(0, length);
187 DCHECK(ReadOnlyHeap::Contains(map));
188
189 HeapObject result =
190 AllocateRawArray(WeakFixedArray::SizeFor(length), allocation);
191 result.set_map_after_allocation(map, SKIP_WRITE_BARRIER);
192 DisallowGarbageCollection no_gc;
193 WeakFixedArray array = WeakFixedArray::cast(result);
194 array.set_length(length);
195 MemsetTagged(ObjectSlot(array.data_start()),
196 read_only_roots().undefined_value(), length);
197
198 return handle(array, isolate());
199 }
200
201 template <typename Impl>
NewWeakFixedArray(int length,AllocationType allocation)202 Handle<WeakFixedArray> FactoryBase<Impl>::NewWeakFixedArray(
203 int length, AllocationType allocation) {
204 DCHECK_LE(0, length);
205 if (length == 0) return impl()->empty_weak_fixed_array();
206 return NewWeakFixedArrayWithMap(read_only_roots().weak_fixed_array_map(),
207 length, allocation);
208 }
209
210 template <typename Impl>
NewByteArray(int length,AllocationType allocation)211 Handle<ByteArray> FactoryBase<Impl>::NewByteArray(int length,
212 AllocationType allocation) {
213 if (length < 0 || length > ByteArray::kMaxLength) {
214 FATAL("Fatal JavaScript invalid size error %d", length);
215 UNREACHABLE();
216 }
217 if (length == 0) return impl()->empty_byte_array();
218 int size = ByteArray::SizeFor(length);
219 HeapObject result = AllocateRawWithImmortalMap(
220 size, allocation, read_only_roots().byte_array_map());
221 DisallowGarbageCollection no_gc;
222 ByteArray array = ByteArray::cast(result);
223 array.set_length(length);
224 array.clear_padding();
225 return handle(array, isolate());
226 }
227
228 template <typename Impl>
NewBytecodeArray(int length,const byte * raw_bytecodes,int frame_size,int parameter_count,Handle<FixedArray> constant_pool)229 Handle<BytecodeArray> FactoryBase<Impl>::NewBytecodeArray(
230 int length, const byte* raw_bytecodes, int frame_size, int parameter_count,
231 Handle<FixedArray> constant_pool) {
232 if (length < 0 || length > BytecodeArray::kMaxLength) {
233 FATAL("Fatal JavaScript invalid size error %d", length);
234 UNREACHABLE();
235 }
236 // Bytecode array is AllocationType::kOld, so constant pool array should be
237 // too.
238 DCHECK(!Heap::InYoungGeneration(*constant_pool));
239
240 int size = BytecodeArray::SizeFor(length);
241 HeapObject result = AllocateRawWithImmortalMap(
242 size, AllocationType::kOld, read_only_roots().bytecode_array_map());
243 DisallowGarbageCollection no_gc;
244 BytecodeArray instance = BytecodeArray::cast(result);
245 instance.set_length(length);
246 instance.set_frame_size(frame_size);
247 instance.set_parameter_count(parameter_count);
248 instance.set_incoming_new_target_or_generator_register(
249 interpreter::Register::invalid_value());
250 instance.reset_osr_urgency_and_install_target();
251 instance.set_bytecode_age(BytecodeArray::kNoAgeBytecodeAge);
252 instance.set_constant_pool(*constant_pool);
253 instance.set_handler_table(read_only_roots().empty_byte_array(),
254 SKIP_WRITE_BARRIER);
255 instance.set_source_position_table(read_only_roots().undefined_value(),
256 kReleaseStore, SKIP_WRITE_BARRIER);
257 CopyBytes(reinterpret_cast<byte*>(instance.GetFirstBytecodeAddress()),
258 raw_bytecodes, length);
259 instance.clear_padding();
260 return handle(instance, isolate());
261 }
262
263 template <typename Impl>
NewScript(Handle<PrimitiveHeapObject> source)264 Handle<Script> FactoryBase<Impl>::NewScript(
265 Handle<PrimitiveHeapObject> source) {
266 return NewScriptWithId(source, isolate()->GetNextScriptId());
267 }
268
269 template <typename Impl>
NewScriptWithId(Handle<PrimitiveHeapObject> source,int script_id)270 Handle<Script> FactoryBase<Impl>::NewScriptWithId(
271 Handle<PrimitiveHeapObject> source, int script_id) {
272 DCHECK(source->IsString() || source->IsUndefined());
273 // Create and initialize script object.
274 ReadOnlyRoots roots = read_only_roots();
275 Handle<Script> script = handle(
276 NewStructInternal<Script>(SCRIPT_TYPE, AllocationType::kOld), isolate());
277 {
278 DisallowGarbageCollection no_gc;
279 Script raw = *script;
280 raw.set_source(*source);
281 raw.set_name(roots.undefined_value(), SKIP_WRITE_BARRIER);
282 raw.set_id(script_id);
283 raw.set_line_offset(0);
284 raw.set_column_offset(0);
285 raw.set_context_data(roots.undefined_value(), SKIP_WRITE_BARRIER);
286 raw.set_type(Script::TYPE_NORMAL);
287 raw.set_line_ends(roots.undefined_value(), SKIP_WRITE_BARRIER);
288 raw.set_eval_from_shared_or_wrapped_arguments_or_sfi_table(
289 roots.undefined_value(), SKIP_WRITE_BARRIER);
290 raw.set_eval_from_position(0);
291 raw.set_shared_function_infos(roots.empty_weak_fixed_array(),
292 SKIP_WRITE_BARRIER);
293 raw.set_flags(0);
294 raw.set_host_defined_options(roots.empty_fixed_array(), SKIP_WRITE_BARRIER);
295 #ifdef V8_SCRIPTORMODULE_LEGACY_LIFETIME
296 raw.set_script_or_modules(roots.empty_array_list());
297 #endif
298 }
299
300 if (script_id != Script::kTemporaryScriptId) {
301 impl()->AddToScriptList(script);
302 }
303
304 LOG(isolate(), ScriptEvent(Logger::ScriptEventType::kCreate, script_id));
305 return script;
306 }
307
308 template <typename Impl>
NewArrayList(int size,AllocationType allocation)309 Handle<ArrayList> FactoryBase<Impl>::NewArrayList(int size,
310 AllocationType allocation) {
311 if (size == 0) return impl()->empty_array_list();
312 Handle<FixedArray> fixed_array =
313 NewFixedArray(size + ArrayList::kFirstIndex, allocation);
314 {
315 DisallowGarbageCollection no_gc;
316 FixedArray raw = *fixed_array;
317 raw.set_map_no_write_barrier(read_only_roots().array_list_map());
318 ArrayList::cast(raw).SetLength(0);
319 }
320 return Handle<ArrayList>::cast(fixed_array);
321 }
322
323 template <typename Impl>
NewSharedFunctionInfoForLiteral(FunctionLiteral * literal,Handle<Script> script,bool is_toplevel)324 Handle<SharedFunctionInfo> FactoryBase<Impl>::NewSharedFunctionInfoForLiteral(
325 FunctionLiteral* literal, Handle<Script> script, bool is_toplevel) {
326 FunctionKind kind = literal->kind();
327 Handle<SharedFunctionInfo> shared =
328 NewSharedFunctionInfo(literal->GetName(isolate()), MaybeHandle<Code>(),
329 Builtin::kCompileLazy, kind);
330 SharedFunctionInfo::InitFromFunctionLiteral(isolate(), shared, literal,
331 is_toplevel);
332 shared->SetScript(read_only_roots(), *script, literal->function_literal_id(),
333 false);
334 return shared;
335 }
336
337 template <typename Impl>
CloneSharedFunctionInfo(Handle<SharedFunctionInfo> other)338 Handle<SharedFunctionInfo> FactoryBase<Impl>::CloneSharedFunctionInfo(
339 Handle<SharedFunctionInfo> other) {
340 Map map = read_only_roots().shared_function_info_map();
341
342 SharedFunctionInfo shared =
343 SharedFunctionInfo::cast(NewWithImmortalMap(map, AllocationType::kOld));
344 DisallowGarbageCollection no_gc;
345
346 shared.CopyFrom(*other);
347 shared.clear_padding();
348
349 return handle(shared, isolate());
350 }
351
352 template <typename Impl>
NewPreparseData(int data_length,int children_length)353 Handle<PreparseData> FactoryBase<Impl>::NewPreparseData(int data_length,
354 int children_length) {
355 int size = PreparseData::SizeFor(data_length, children_length);
356 PreparseData result = PreparseData::cast(AllocateRawWithImmortalMap(
357 size, AllocationType::kOld, read_only_roots().preparse_data_map()));
358 DisallowGarbageCollection no_gc;
359 result.set_data_length(data_length);
360 result.set_children_length(children_length);
361 MemsetTagged(result.inner_data_start(), read_only_roots().null_value(),
362 children_length);
363 result.clear_padding();
364 return handle(result, isolate());
365 }
366
367 template <typename Impl>
368 Handle<UncompiledDataWithoutPreparseData>
NewUncompiledDataWithoutPreparseData(Handle<String> inferred_name,int32_t start_position,int32_t end_position)369 FactoryBase<Impl>::NewUncompiledDataWithoutPreparseData(
370 Handle<String> inferred_name, int32_t start_position,
371 int32_t end_position) {
372 return TorqueGeneratedFactory<Impl>::NewUncompiledDataWithoutPreparseData(
373 inferred_name, start_position, end_position, AllocationType::kOld);
374 }
375
376 template <typename Impl>
377 Handle<UncompiledDataWithPreparseData>
NewUncompiledDataWithPreparseData(Handle<String> inferred_name,int32_t start_position,int32_t end_position,Handle<PreparseData> preparse_data)378 FactoryBase<Impl>::NewUncompiledDataWithPreparseData(
379 Handle<String> inferred_name, int32_t start_position, int32_t end_position,
380 Handle<PreparseData> preparse_data) {
381 return TorqueGeneratedFactory<Impl>::NewUncompiledDataWithPreparseData(
382 inferred_name, start_position, end_position, preparse_data,
383 AllocationType::kOld);
384 }
385
386 template <typename Impl>
387 Handle<UncompiledDataWithoutPreparseDataWithJob>
NewUncompiledDataWithoutPreparseDataWithJob(Handle<String> inferred_name,int32_t start_position,int32_t end_position)388 FactoryBase<Impl>::NewUncompiledDataWithoutPreparseDataWithJob(
389 Handle<String> inferred_name, int32_t start_position,
390 int32_t end_position) {
391 return TorqueGeneratedFactory<
392 Impl>::NewUncompiledDataWithoutPreparseDataWithJob(inferred_name,
393 start_position,
394 end_position,
395 kNullAddress,
396 AllocationType::kOld);
397 }
398
399 template <typename Impl>
400 Handle<UncompiledDataWithPreparseDataAndJob>
NewUncompiledDataWithPreparseDataAndJob(Handle<String> inferred_name,int32_t start_position,int32_t end_position,Handle<PreparseData> preparse_data)401 FactoryBase<Impl>::NewUncompiledDataWithPreparseDataAndJob(
402 Handle<String> inferred_name, int32_t start_position, int32_t end_position,
403 Handle<PreparseData> preparse_data) {
404 return TorqueGeneratedFactory<Impl>::NewUncompiledDataWithPreparseDataAndJob(
405 inferred_name, start_position, end_position, preparse_data, kNullAddress,
406 AllocationType::kOld);
407 }
408
409 template <typename Impl>
NewSharedFunctionInfo(MaybeHandle<String> maybe_name,MaybeHandle<HeapObject> maybe_function_data,Builtin builtin,FunctionKind kind)410 Handle<SharedFunctionInfo> FactoryBase<Impl>::NewSharedFunctionInfo(
411 MaybeHandle<String> maybe_name, MaybeHandle<HeapObject> maybe_function_data,
412 Builtin builtin, FunctionKind kind) {
413 Handle<SharedFunctionInfo> shared = NewSharedFunctionInfo();
414 DisallowGarbageCollection no_gc;
415 SharedFunctionInfo raw = *shared;
416 // Function names are assumed to be flat elsewhere.
417 Handle<String> shared_name;
418 bool has_shared_name = maybe_name.ToHandle(&shared_name);
419 if (has_shared_name) {
420 DCHECK(shared_name->IsFlat());
421 raw.set_name_or_scope_info(*shared_name, kReleaseStore);
422 } else {
423 DCHECK_EQ(raw.name_or_scope_info(kAcquireLoad),
424 SharedFunctionInfo::kNoSharedNameSentinel);
425 }
426
427 Handle<HeapObject> function_data;
428 if (maybe_function_data.ToHandle(&function_data)) {
429 // If we pass function_data then we shouldn't pass a builtin index, and
430 // the function_data should not be code with a builtin.
431 DCHECK(!Builtins::IsBuiltinId(builtin));
432 DCHECK_IMPLIES(function_data->IsCode(),
433 !Code::cast(*function_data).is_builtin());
434 raw.set_function_data(*function_data, kReleaseStore);
435 } else if (Builtins::IsBuiltinId(builtin)) {
436 raw.set_builtin_id(builtin);
437 } else {
438 DCHECK(raw.HasBuiltinId());
439 DCHECK_EQ(Builtin::kIllegal, raw.builtin_id());
440 }
441
442 raw.CalculateConstructAsBuiltin();
443 raw.set_kind(kind);
444
445 #ifdef VERIFY_HEAP
446 if (FLAG_verify_heap) raw.SharedFunctionInfoVerify(isolate());
447 #endif // VERIFY_HEAP
448 return shared;
449 }
450
451 template <typename Impl>
452 Handle<ObjectBoilerplateDescription>
NewObjectBoilerplateDescription(int boilerplate,int all_properties,int index_keys,bool has_seen_proto)453 FactoryBase<Impl>::NewObjectBoilerplateDescription(int boilerplate,
454 int all_properties,
455 int index_keys,
456 bool has_seen_proto) {
457 DCHECK_GE(boilerplate, 0);
458 DCHECK_GE(all_properties, index_keys);
459 DCHECK_GE(index_keys, 0);
460
461 int backing_store_size =
462 all_properties - index_keys - (has_seen_proto ? 1 : 0);
463 DCHECK_GE(backing_store_size, 0);
464 bool has_different_size_backing_store = boilerplate != backing_store_size;
465
466 // Space for name and value for every boilerplate property + LiteralType flag.
467 int size =
468 2 * boilerplate + ObjectBoilerplateDescription::kDescriptionStartIndex;
469
470 if (has_different_size_backing_store) {
471 // An extra entry for the backing store size.
472 size++;
473 }
474
475 Handle<ObjectBoilerplateDescription> description =
476 Handle<ObjectBoilerplateDescription>::cast(NewFixedArrayWithMap(
477 read_only_roots().object_boilerplate_description_map_handle(), size,
478 AllocationType::kOld));
479
480 if (has_different_size_backing_store) {
481 DCHECK_IMPLIES((boilerplate == (all_properties - index_keys)),
482 has_seen_proto);
483 description->set_backing_store_size(backing_store_size);
484 }
485
486 description->set_flags(0);
487
488 return description;
489 }
490
491 template <typename Impl>
492 Handle<ArrayBoilerplateDescription>
NewArrayBoilerplateDescription(ElementsKind elements_kind,Handle<FixedArrayBase> constant_values)493 FactoryBase<Impl>::NewArrayBoilerplateDescription(
494 ElementsKind elements_kind, Handle<FixedArrayBase> constant_values) {
495 auto result = NewStructInternal<ArrayBoilerplateDescription>(
496 ARRAY_BOILERPLATE_DESCRIPTION_TYPE, AllocationType::kOld);
497 DisallowGarbageCollection no_gc;
498 result.set_elements_kind(elements_kind);
499 result.set_constant_elements(*constant_values);
500 return handle(result, isolate());
501 }
502
503 template <typename Impl>
504 Handle<RegExpBoilerplateDescription>
NewRegExpBoilerplateDescription(Handle<FixedArray> data,Handle<String> source,Smi flags)505 FactoryBase<Impl>::NewRegExpBoilerplateDescription(Handle<FixedArray> data,
506 Handle<String> source,
507 Smi flags) {
508 auto result = NewStructInternal<RegExpBoilerplateDescription>(
509 REG_EXP_BOILERPLATE_DESCRIPTION_TYPE, AllocationType::kOld);
510 DisallowGarbageCollection no_gc;
511 result.set_data(*data);
512 result.set_source(*source);
513 result.set_flags(flags.value());
514 return handle(result, isolate());
515 }
516
517 template <typename Impl>
518 Handle<TemplateObjectDescription>
NewTemplateObjectDescription(Handle<FixedArray> raw_strings,Handle<FixedArray> cooked_strings)519 FactoryBase<Impl>::NewTemplateObjectDescription(
520 Handle<FixedArray> raw_strings, Handle<FixedArray> cooked_strings) {
521 DCHECK_EQ(raw_strings->length(), cooked_strings->length());
522 DCHECK_LT(0, raw_strings->length());
523 auto result = NewStructInternal<TemplateObjectDescription>(
524 TEMPLATE_OBJECT_DESCRIPTION_TYPE, AllocationType::kOld);
525 DisallowGarbageCollection no_gc;
526 result.set_raw_strings(*raw_strings);
527 result.set_cooked_strings(*cooked_strings);
528 return handle(result, isolate());
529 }
530
531 template <typename Impl>
NewFeedbackMetadata(int slot_count,int create_closure_slot_count,AllocationType allocation)532 Handle<FeedbackMetadata> FactoryBase<Impl>::NewFeedbackMetadata(
533 int slot_count, int create_closure_slot_count, AllocationType allocation) {
534 DCHECK_LE(0, slot_count);
535 int size = FeedbackMetadata::SizeFor(slot_count);
536 FeedbackMetadata result = FeedbackMetadata::cast(AllocateRawWithImmortalMap(
537 size, allocation, read_only_roots().feedback_metadata_map()));
538 result.set_slot_count(slot_count);
539 result.set_create_closure_slot_count(create_closure_slot_count);
540
541 // Initialize the data section to 0.
542 int data_size = size - FeedbackMetadata::kHeaderSize;
543 Address data_start = result.address() + FeedbackMetadata::kHeaderSize;
544 memset(reinterpret_cast<byte*>(data_start), 0, data_size);
545 // Fields have been zeroed out but not initialized, so this object will not
546 // pass object verification at this point.
547 return handle(result, isolate());
548 }
549
550 template <typename Impl>
NewCoverageInfo(const ZoneVector<SourceRange> & slots)551 Handle<CoverageInfo> FactoryBase<Impl>::NewCoverageInfo(
552 const ZoneVector<SourceRange>& slots) {
553 const int slot_count = static_cast<int>(slots.size());
554
555 int size = CoverageInfo::SizeFor(slot_count);
556 Map map = read_only_roots().coverage_info_map();
557 CoverageInfo info = CoverageInfo::cast(
558 AllocateRawWithImmortalMap(size, AllocationType::kOld, map));
559 info.set_slot_count(slot_count);
560 for (int i = 0; i < slot_count; i++) {
561 SourceRange range = slots[i];
562 info.InitializeSlot(i, range.start, range.end);
563 }
564 return handle(info, isolate());
565 }
566
567 template <typename Impl>
MakeOrFindTwoCharacterString(uint16_t c1,uint16_t c2)568 Handle<String> FactoryBase<Impl>::MakeOrFindTwoCharacterString(uint16_t c1,
569 uint16_t c2) {
570 if ((c1 | c2) <= unibrow::Latin1::kMaxChar) {
571 uint8_t buffer[] = {static_cast<uint8_t>(c1), static_cast<uint8_t>(c2)};
572 return InternalizeString(base::Vector<const uint8_t>(buffer, 2));
573 }
574 uint16_t buffer[] = {c1, c2};
575 return InternalizeString(base::Vector<const uint16_t>(buffer, 2));
576 }
577
578 template <typename Impl>
579 template <class StringTableKey>
InternalizeStringWithKey(StringTableKey * key)580 Handle<String> FactoryBase<Impl>::InternalizeStringWithKey(
581 StringTableKey* key) {
582 return isolate()->string_table()->LookupKey(isolate(), key);
583 }
584
585 template EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)
586 Handle<String> FactoryBase<Factory>::InternalizeStringWithKey(
587 OneByteStringKey* key);
588 template EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)
589 Handle<String> FactoryBase<Factory>::InternalizeStringWithKey(
590 TwoByteStringKey* key);
591 template EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)
592 Handle<String> FactoryBase<Factory>::InternalizeStringWithKey(
593 SeqOneByteSubStringKey* key);
594 template EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)
595 Handle<String> FactoryBase<Factory>::InternalizeStringWithKey(
596 SeqTwoByteSubStringKey* key);
597
598 template EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)
599 Handle<String> FactoryBase<LocalFactory>::InternalizeStringWithKey(
600 OneByteStringKey* key);
601 template EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)
602 Handle<String> FactoryBase<LocalFactory>::InternalizeStringWithKey(
603 TwoByteStringKey* key);
604
605 template <typename Impl>
InternalizeString(const base::Vector<const uint8_t> & string,bool convert_encoding)606 Handle<String> FactoryBase<Impl>::InternalizeString(
607 const base::Vector<const uint8_t>& string, bool convert_encoding) {
608 SequentialStringKey<uint8_t> key(string, HashSeed(read_only_roots()),
609 convert_encoding);
610 return InternalizeStringWithKey(&key);
611 }
612
613 template <typename Impl>
InternalizeString(const base::Vector<const uint16_t> & string,bool convert_encoding)614 Handle<String> FactoryBase<Impl>::InternalizeString(
615 const base::Vector<const uint16_t>& string, bool convert_encoding) {
616 SequentialStringKey<uint16_t> key(string, HashSeed(read_only_roots()),
617 convert_encoding);
618 return InternalizeStringWithKey(&key);
619 }
620
621 template <typename Impl>
NewOneByteInternalizedString(const base::Vector<const uint8_t> & str,uint32_t raw_hash_field)622 Handle<SeqOneByteString> FactoryBase<Impl>::NewOneByteInternalizedString(
623 const base::Vector<const uint8_t>& str, uint32_t raw_hash_field) {
624 Handle<SeqOneByteString> result =
625 AllocateRawOneByteInternalizedString(str.length(), raw_hash_field);
626 // No synchronization is needed since the shared string hasn't yet escaped to
627 // script.
628 DisallowGarbageCollection no_gc;
629 MemCopy(result->GetChars(no_gc, SharedStringAccessGuardIfNeeded::NotNeeded()),
630 str.begin(), str.length());
631 return result;
632 }
633
634 template <typename Impl>
NewTwoByteInternalizedString(const base::Vector<const base::uc16> & str,uint32_t raw_hash_field)635 Handle<SeqTwoByteString> FactoryBase<Impl>::NewTwoByteInternalizedString(
636 const base::Vector<const base::uc16>& str, uint32_t raw_hash_field) {
637 Handle<SeqTwoByteString> result =
638 AllocateRawTwoByteInternalizedString(str.length(), raw_hash_field);
639 // No synchronization is needed since the shared string hasn't yet escaped to
640 // script.
641 DisallowGarbageCollection no_gc;
642 MemCopy(result->GetChars(no_gc, SharedStringAccessGuardIfNeeded::NotNeeded()),
643 str.begin(), str.length() * base::kUC16Size);
644 return result;
645 }
646
647 template <typename Impl>
648 template <typename SeqStringT>
NewRawStringWithMap(int length,Map map,AllocationType allocation)649 MaybeHandle<SeqStringT> FactoryBase<Impl>::NewRawStringWithMap(
650 int length, Map map, AllocationType allocation) {
651 DCHECK(SeqStringT::IsCompatibleMap(map, read_only_roots()));
652 DCHECK_IMPLIES(!StringShape(map).IsShared(),
653 RefineAllocationTypeForInPlaceInternalizableString(
654 allocation, map) == allocation);
655 if (length > String::kMaxLength || length < 0) {
656 THROW_NEW_ERROR(isolate(), NewInvalidStringLengthError(), SeqStringT);
657 }
658 DCHECK_GT(length, 0); // Use Factory::empty_string() instead.
659 int size = SeqStringT::SizeFor(length);
660 DCHECK_GE(SeqStringT::kMaxSize, size);
661
662 SeqStringT string =
663 SeqStringT::cast(AllocateRawWithImmortalMap(size, allocation, map));
664 DisallowGarbageCollection no_gc;
665 string.set_length(length);
666 string.set_raw_hash_field(String::kEmptyHashField);
667 DCHECK_EQ(size, string.Size());
668 return handle(string, isolate());
669 }
670
671 template <typename Impl>
NewRawOneByteString(int length,AllocationType allocation)672 MaybeHandle<SeqOneByteString> FactoryBase<Impl>::NewRawOneByteString(
673 int length, AllocationType allocation) {
674 Map map = read_only_roots().one_byte_string_map();
675 return NewRawStringWithMap<SeqOneByteString>(
676 length, map,
677 RefineAllocationTypeForInPlaceInternalizableString(allocation, map));
678 }
679
680 template <typename Impl>
NewRawTwoByteString(int length,AllocationType allocation)681 MaybeHandle<SeqTwoByteString> FactoryBase<Impl>::NewRawTwoByteString(
682 int length, AllocationType allocation) {
683 Map map = read_only_roots().string_map();
684 return NewRawStringWithMap<SeqTwoByteString>(
685 length, map,
686 RefineAllocationTypeForInPlaceInternalizableString(allocation, map));
687 }
688
689 template <typename Impl>
NewRawSharedOneByteString(int length)690 MaybeHandle<SeqOneByteString> FactoryBase<Impl>::NewRawSharedOneByteString(
691 int length) {
692 return NewRawStringWithMap<SeqOneByteString>(
693 length, read_only_roots().shared_one_byte_string_map(),
694 AllocationType::kSharedOld);
695 }
696
697 template <typename Impl>
NewRawSharedTwoByteString(int length)698 MaybeHandle<SeqTwoByteString> FactoryBase<Impl>::NewRawSharedTwoByteString(
699 int length) {
700 return NewRawStringWithMap<SeqTwoByteString>(
701 length, read_only_roots().shared_string_map(),
702 AllocationType::kSharedOld);
703 }
704
705 template <typename Impl>
NewConsString(Handle<String> left,Handle<String> right,AllocationType allocation)706 MaybeHandle<String> FactoryBase<Impl>::NewConsString(
707 Handle<String> left, Handle<String> right, AllocationType allocation) {
708 if (left->IsThinString()) {
709 left = handle(ThinString::cast(*left).actual(), isolate());
710 }
711 if (right->IsThinString()) {
712 right = handle(ThinString::cast(*right).actual(), isolate());
713 }
714 int left_length = left->length();
715 if (left_length == 0) return right;
716 int right_length = right->length();
717 if (right_length == 0) return left;
718
719 int length = left_length + right_length;
720
721 if (length == 2) {
722 uint16_t c1 = left->Get(0, isolate());
723 uint16_t c2 = right->Get(0, isolate());
724 return MakeOrFindTwoCharacterString(c1, c2);
725 }
726
727 // Make sure that an out of memory exception is thrown if the length
728 // of the new cons string is too large.
729 if (length > String::kMaxLength || length < 0) {
730 THROW_NEW_ERROR(isolate(), NewInvalidStringLengthError(), String);
731 }
732
733 bool left_is_one_byte = left->IsOneByteRepresentation();
734 bool right_is_one_byte = right->IsOneByteRepresentation();
735 bool is_one_byte = left_is_one_byte && right_is_one_byte;
736
737 // If the resulting string is small make a flat string.
738 if (length < ConsString::kMinLength) {
739 // Note that neither of the two inputs can be a slice because:
740 STATIC_ASSERT(ConsString::kMinLength <= SlicedString::kMinLength);
741 DCHECK(left->IsFlat());
742 DCHECK(right->IsFlat());
743
744 STATIC_ASSERT(ConsString::kMinLength <= String::kMaxLength);
745 if (is_one_byte) {
746 Handle<SeqOneByteString> result =
747 NewRawOneByteString(length, allocation).ToHandleChecked();
748 DisallowGarbageCollection no_gc;
749 SharedStringAccessGuardIfNeeded access_guard(isolate());
750 uint8_t* dest = result->GetChars(no_gc, access_guard);
751 // Copy left part.
752 {
753 const uint8_t* src =
754 left->template GetChars<uint8_t>(isolate(), no_gc, access_guard);
755 CopyChars(dest, src, left_length);
756 }
757 // Copy right part.
758 {
759 const uint8_t* src =
760 right->template GetChars<uint8_t>(isolate(), no_gc, access_guard);
761 CopyChars(dest + left_length, src, right_length);
762 }
763 return result;
764 }
765
766 Handle<SeqTwoByteString> result =
767 NewRawTwoByteString(length, allocation).ToHandleChecked();
768
769 DisallowGarbageCollection no_gc;
770 SharedStringAccessGuardIfNeeded access_guard(isolate());
771 base::uc16* sink = result->GetChars(no_gc, access_guard);
772 String::WriteToFlat(*left, sink, 0, left->length(), isolate(),
773 access_guard);
774 String::WriteToFlat(*right, sink + left->length(), 0, right->length(),
775 isolate(), access_guard);
776 return result;
777 }
778
779 return NewConsString(left, right, length, is_one_byte, allocation);
780 }
781
782 template <typename Impl>
NewConsString(Handle<String> left,Handle<String> right,int length,bool one_byte,AllocationType allocation)783 Handle<String> FactoryBase<Impl>::NewConsString(Handle<String> left,
784 Handle<String> right,
785 int length, bool one_byte,
786 AllocationType allocation) {
787 DCHECK(!left->IsThinString());
788 DCHECK(!right->IsThinString());
789 DCHECK_GE(length, ConsString::kMinLength);
790 DCHECK_LE(length, String::kMaxLength);
791
792 ConsString result = ConsString::cast(
793 one_byte ? NewWithImmortalMap(
794 read_only_roots().cons_one_byte_string_map(), allocation)
795 : NewWithImmortalMap(read_only_roots().cons_string_map(),
796 allocation));
797
798 DisallowGarbageCollection no_gc;
799 WriteBarrierMode mode = result.GetWriteBarrierMode(no_gc);
800 result.set_raw_hash_field(String::kEmptyHashField);
801 result.set_length(length);
802 result.set_first(*left, mode);
803 result.set_second(*right, mode);
804 return handle(result, isolate());
805 }
806
807 template <typename Impl>
NewBigInt(int length,AllocationType allocation)808 Handle<FreshlyAllocatedBigInt> FactoryBase<Impl>::NewBigInt(
809 int length, AllocationType allocation) {
810 if (length < 0 || length > BigInt::kMaxLength) {
811 FATAL("Fatal JavaScript invalid size error %d", length);
812 UNREACHABLE();
813 }
814 HeapObject result = AllocateRawWithImmortalMap(
815 BigInt::SizeFor(length), allocation, read_only_roots().bigint_map());
816 DisallowGarbageCollection no_gc;
817 FreshlyAllocatedBigInt bigint = FreshlyAllocatedBigInt::cast(result);
818 bigint.clear_padding();
819 return handle(bigint, isolate());
820 }
821
822 template <typename Impl>
NewScopeInfo(int length,AllocationType type)823 Handle<ScopeInfo> FactoryBase<Impl>::NewScopeInfo(int length,
824 AllocationType type) {
825 DCHECK(type == AllocationType::kOld || type == AllocationType::kReadOnly);
826 int size = ScopeInfo::SizeFor(length);
827 HeapObject obj = AllocateRawWithImmortalMap(
828 size, type, read_only_roots().scope_info_map());
829 ScopeInfo scope_info = ScopeInfo::cast(obj);
830 MemsetTagged(scope_info.data_start(), read_only_roots().undefined_value(),
831 length);
832 return handle(scope_info, isolate());
833 }
834
835 template <typename Impl>
NewSourceTextModuleInfo()836 Handle<SourceTextModuleInfo> FactoryBase<Impl>::NewSourceTextModuleInfo() {
837 return Handle<SourceTextModuleInfo>::cast(NewFixedArrayWithMap(
838 read_only_roots().module_info_map_handle(), SourceTextModuleInfo::kLength,
839 AllocationType::kOld));
840 }
841
842 template <typename Impl>
NewSharedFunctionInfo()843 Handle<SharedFunctionInfo> FactoryBase<Impl>::NewSharedFunctionInfo() {
844 Map map = read_only_roots().shared_function_info_map();
845
846 SharedFunctionInfo shared =
847 SharedFunctionInfo::cast(NewWithImmortalMap(map, AllocationType::kOld));
848 DisallowGarbageCollection no_gc;
849 int unique_id = -1;
850 #if V8_SFI_HAS_UNIQUE_ID
851 unique_id = isolate()->GetNextUniqueSharedFunctionInfoId();
852 #endif // V8_SFI_HAS_UNIQUE_ID
853
854 shared.Init(read_only_roots(), unique_id);
855
856 #ifdef VERIFY_HEAP
857 if (FLAG_verify_heap) shared.SharedFunctionInfoVerify(isolate());
858 #endif // VERIFY_HEAP
859 return handle(shared, isolate());
860 }
861
862 template <typename Impl>
NewDescriptorArray(int number_of_descriptors,int slack,AllocationType allocation)863 Handle<DescriptorArray> FactoryBase<Impl>::NewDescriptorArray(
864 int number_of_descriptors, int slack, AllocationType allocation) {
865 int number_of_all_descriptors = number_of_descriptors + slack;
866 // Zero-length case must be handled outside.
867 DCHECK_LT(0, number_of_all_descriptors);
868 int size = DescriptorArray::SizeFor(number_of_all_descriptors);
869 HeapObject obj = AllocateRawWithImmortalMap(
870 size, allocation, read_only_roots().descriptor_array_map());
871 DescriptorArray array = DescriptorArray::cast(obj);
872 array.Initialize(read_only_roots().empty_enum_cache(),
873 read_only_roots().undefined_value(), number_of_descriptors,
874 slack);
875 return handle(array, isolate());
876 }
877
878 template <typename Impl>
NewClassPositions(int start,int end)879 Handle<ClassPositions> FactoryBase<Impl>::NewClassPositions(int start,
880 int end) {
881 auto result = NewStructInternal<ClassPositions>(CLASS_POSITIONS_TYPE,
882 AllocationType::kOld);
883 result.set_start(start);
884 result.set_end(end);
885 return handle(result, isolate());
886 }
887
888 template <typename Impl>
889 Handle<SeqOneByteString>
AllocateRawOneByteInternalizedString(int length,uint32_t raw_hash_field)890 FactoryBase<Impl>::AllocateRawOneByteInternalizedString(
891 int length, uint32_t raw_hash_field) {
892 CHECK_GE(String::kMaxLength, length);
893 // The canonical empty_string is the only zero-length string we allow.
894 DCHECK_IMPLIES(length == 0, !impl()->EmptyStringRootIsInitialized());
895
896 Map map = read_only_roots().one_byte_internalized_string_map();
897 int size = SeqOneByteString::SizeFor(length);
898 HeapObject result = AllocateRawWithImmortalMap(
899 size,
900 RefineAllocationTypeForInPlaceInternalizableString(
901 impl()->CanAllocateInReadOnlySpace() ? AllocationType::kReadOnly
902 : AllocationType::kOld,
903 map),
904 map);
905 SeqOneByteString answer = SeqOneByteString::cast(result);
906 DisallowGarbageCollection no_gc;
907 answer.set_length(length);
908 answer.set_raw_hash_field(raw_hash_field);
909 DCHECK_EQ(size, answer.Size());
910 return handle(answer, isolate());
911 }
912
913 template <typename Impl>
914 Handle<SeqTwoByteString>
AllocateRawTwoByteInternalizedString(int length,uint32_t raw_hash_field)915 FactoryBase<Impl>::AllocateRawTwoByteInternalizedString(
916 int length, uint32_t raw_hash_field) {
917 CHECK_GE(String::kMaxLength, length);
918 DCHECK_NE(0, length); // Use Heap::empty_string() instead.
919
920 Map map = read_only_roots().internalized_string_map();
921 int size = SeqTwoByteString::SizeFor(length);
922 SeqTwoByteString answer = SeqTwoByteString::cast(AllocateRawWithImmortalMap(
923 size,
924 RefineAllocationTypeForInPlaceInternalizableString(AllocationType::kOld,
925 map),
926 map));
927 DisallowGarbageCollection no_gc;
928 answer.set_length(length);
929 answer.set_raw_hash_field(raw_hash_field);
930 DCHECK_EQ(size, answer.Size());
931 return handle(answer, isolate());
932 }
933
934 template <typename Impl>
AllocateRawArray(int size,AllocationType allocation)935 HeapObject FactoryBase<Impl>::AllocateRawArray(int size,
936 AllocationType allocation) {
937 HeapObject result = AllocateRaw(size, allocation);
938 if (!V8_ENABLE_THIRD_PARTY_HEAP_BOOL &&
939 (size >
940 isolate()->heap()->AsHeap()->MaxRegularHeapObjectSize(allocation)) &&
941 FLAG_use_marking_progress_bar) {
942 LargePage::FromHeapObject(result)->ProgressBar().Enable();
943 }
944 return result;
945 }
946
947 template <typename Impl>
AllocateRawFixedArray(int length,AllocationType allocation)948 HeapObject FactoryBase<Impl>::AllocateRawFixedArray(int length,
949 AllocationType allocation) {
950 if (length < 0 || length > FixedArray::kMaxLength) {
951 FATAL("Fatal JavaScript invalid size error %d", length);
952 UNREACHABLE();
953 }
954 return AllocateRawArray(FixedArray::SizeFor(length), allocation);
955 }
956
957 template <typename Impl>
AllocateRawWeakArrayList(int capacity,AllocationType allocation)958 HeapObject FactoryBase<Impl>::AllocateRawWeakArrayList(
959 int capacity, AllocationType allocation) {
960 if (capacity < 0 || capacity > WeakArrayList::kMaxCapacity) {
961 FATAL("Fatal JavaScript invalid size error %d", capacity);
962 UNREACHABLE();
963 }
964 return AllocateRawArray(WeakArrayList::SizeForCapacity(capacity), allocation);
965 }
966
967 template <typename Impl>
NewWithImmortalMap(Map map,AllocationType allocation)968 HeapObject FactoryBase<Impl>::NewWithImmortalMap(Map map,
969 AllocationType allocation) {
970 return AllocateRawWithImmortalMap(map.instance_size(), allocation, map);
971 }
972
973 template <typename Impl>
AllocateRawWithImmortalMap(int size,AllocationType allocation,Map map,AllocationAlignment alignment)974 HeapObject FactoryBase<Impl>::AllocateRawWithImmortalMap(
975 int size, AllocationType allocation, Map map,
976 AllocationAlignment alignment) {
977 // TODO(delphick): Potentially you could also pass a immortal immovable Map
978 // from MAP_SPACE here, like external_map or message_object_map, but currently
979 // noone does so this check is sufficient.
980 DCHECK(ReadOnlyHeap::Contains(map));
981 HeapObject result = AllocateRaw(size, allocation, alignment);
982 DisallowGarbageCollection no_gc;
983 result.set_map_after_allocation(map, SKIP_WRITE_BARRIER);
984 return result;
985 }
986
987 template <typename Impl>
AllocateRaw(int size,AllocationType allocation,AllocationAlignment alignment)988 HeapObject FactoryBase<Impl>::AllocateRaw(int size, AllocationType allocation,
989 AllocationAlignment alignment) {
990 return impl()->AllocateRaw(size, allocation, alignment);
991 }
992
993 template <typename Impl>
994 Handle<SwissNameDictionary>
NewSwissNameDictionaryWithCapacity(int capacity,AllocationType allocation)995 FactoryBase<Impl>::NewSwissNameDictionaryWithCapacity(
996 int capacity, AllocationType allocation) {
997 DCHECK(SwissNameDictionary::IsValidCapacity(capacity));
998
999 if (capacity == 0) {
1000 DCHECK_NE(read_only_roots().at(RootIndex::kEmptySwissPropertyDictionary),
1001 kNullAddress);
1002
1003 return read_only_roots().empty_swiss_property_dictionary_handle();
1004 }
1005
1006 if (capacity < 0 || capacity > SwissNameDictionary::MaxCapacity()) {
1007 FATAL("Fatal JavaScript invalid size error %d", capacity);
1008 UNREACHABLE();
1009 }
1010
1011 int meta_table_length = SwissNameDictionary::MetaTableSizeFor(capacity);
1012 Handle<ByteArray> meta_table =
1013 impl()->NewByteArray(meta_table_length, allocation);
1014
1015 Map map = read_only_roots().swiss_name_dictionary_map();
1016 int size = SwissNameDictionary::SizeFor(capacity);
1017 SwissNameDictionary table = SwissNameDictionary::cast(
1018 AllocateRawWithImmortalMap(size, allocation, map));
1019 DisallowGarbageCollection no_gc;
1020 table.Initialize(isolate(), *meta_table, capacity);
1021 return handle(table, isolate());
1022 }
1023
1024 template <typename Impl>
NewSwissNameDictionary(int at_least_space_for,AllocationType allocation)1025 Handle<SwissNameDictionary> FactoryBase<Impl>::NewSwissNameDictionary(
1026 int at_least_space_for, AllocationType allocation) {
1027 return NewSwissNameDictionaryWithCapacity(
1028 SwissNameDictionary::CapacityFor(at_least_space_for), allocation);
1029 }
1030
1031 template <typename Impl>
1032 Handle<FunctionTemplateRareData>
NewFunctionTemplateRareData()1033 FactoryBase<Impl>::NewFunctionTemplateRareData() {
1034 auto function_template_rare_data =
1035 NewStructInternal<FunctionTemplateRareData>(
1036 FUNCTION_TEMPLATE_RARE_DATA_TYPE, AllocationType::kOld);
1037 DisallowGarbageCollection no_gc;
1038 function_template_rare_data.set_c_function_overloads(
1039 *impl()->empty_fixed_array(), SKIP_WRITE_BARRIER);
1040 return handle(function_template_rare_data, isolate());
1041 }
1042
1043 template <typename Impl>
GetInPlaceInternalizedStringMap(Map from_string_map)1044 MaybeHandle<Map> FactoryBase<Impl>::GetInPlaceInternalizedStringMap(
1045 Map from_string_map) {
1046 InstanceType instance_type = from_string_map.instance_type();
1047 MaybeHandle<Map> map;
1048 switch (instance_type) {
1049 case STRING_TYPE:
1050 case SHARED_STRING_TYPE:
1051 map = read_only_roots().internalized_string_map_handle();
1052 break;
1053 case ONE_BYTE_STRING_TYPE:
1054 case SHARED_ONE_BYTE_STRING_TYPE:
1055 map = read_only_roots().one_byte_internalized_string_map_handle();
1056 break;
1057 case EXTERNAL_STRING_TYPE:
1058 map = read_only_roots().external_internalized_string_map_handle();
1059 break;
1060 case EXTERNAL_ONE_BYTE_STRING_TYPE:
1061 map =
1062 read_only_roots().external_one_byte_internalized_string_map_handle();
1063 break;
1064 default:
1065 break;
1066 }
1067 DCHECK_EQ(!map.is_null(), String::IsInPlaceInternalizable(instance_type));
1068 return map;
1069 }
1070
1071 template <typename Impl>
GetStringMigrationSentinelMap(InstanceType from_string_type)1072 Handle<Map> FactoryBase<Impl>::GetStringMigrationSentinelMap(
1073 InstanceType from_string_type) {
1074 Handle<Map> map;
1075 switch (from_string_type) {
1076 case SHARED_STRING_TYPE:
1077 map = read_only_roots().seq_string_migration_sentinel_map_handle();
1078 break;
1079 case SHARED_ONE_BYTE_STRING_TYPE:
1080 map =
1081 read_only_roots().one_byte_seq_string_migration_sentinel_map_handle();
1082 break;
1083 default:
1084 UNREACHABLE();
1085 }
1086 DCHECK_EQ(map->instance_type(), from_string_type);
1087 return map;
1088 }
1089
1090 template <typename Impl>
1091 AllocationType
RefineAllocationTypeForInPlaceInternalizableString(AllocationType allocation,Map string_map)1092 FactoryBase<Impl>::RefineAllocationTypeForInPlaceInternalizableString(
1093 AllocationType allocation, Map string_map) {
1094 #ifdef DEBUG
1095 InstanceType instance_type = string_map.instance_type();
1096 DCHECK(InstanceTypeChecker::IsInternalizedString(instance_type) ||
1097 String::IsInPlaceInternalizable(instance_type));
1098 #endif
1099 if (FLAG_single_generation && allocation == AllocationType::kYoung) {
1100 allocation = AllocationType::kOld;
1101 }
1102 if (allocation != AllocationType::kOld) return allocation;
1103 return impl()->AllocationTypeForInPlaceInternalizableString();
1104 }
1105
1106 // Instantiate FactoryBase for the two variants we want.
1107 template class EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE) FactoryBase<Factory>;
1108 template class EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)
1109 FactoryBase<LocalFactory>;
1110
1111 } // namespace internal
1112 } // namespace v8
1113