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