• 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