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