• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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