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