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