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