1 // Copyright 2014 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.h"
6
7 #include "src/accessors.h"
8 #include "src/allocation-site-scopes.h"
9 #include "src/ast/ast-source-ranges.h"
10 #include "src/ast/ast.h"
11 #include "src/base/bits.h"
12 #include "src/bootstrapper.h"
13 #include "src/builtins/constants-table-builder.h"
14 #include "src/compiler.h"
15 #include "src/conversions.h"
16 #include "src/interpreter/interpreter.h"
17 #include "src/isolate-inl.h"
18 #include "src/macro-assembler.h"
19 #include "src/objects/api-callbacks.h"
20 #include "src/objects/bigint.h"
21 #include "src/objects/debug-objects-inl.h"
22 #include "src/objects/frame-array-inl.h"
23 #include "src/objects/microtask-inl.h"
24 #include "src/objects/module.h"
25 #include "src/objects/promise-inl.h"
26 #include "src/objects/scope-info.h"
27 #include "src/unicode-cache.h"
28 #include "src/unicode-decoder.h"
29
30 namespace v8 {
31 namespace internal {
32
33 namespace {
34
ComputeCodeObjectSize(const CodeDesc & desc)35 int ComputeCodeObjectSize(const CodeDesc& desc) {
36 bool has_unwinding_info = desc.unwinding_info != nullptr;
37 DCHECK((has_unwinding_info && desc.unwinding_info_size > 0) ||
38 (!has_unwinding_info && desc.unwinding_info_size == 0));
39 int body_size = desc.instr_size;
40 int unwinding_info_size_field_size = kInt64Size;
41 if (has_unwinding_info) {
42 body_size = RoundUp(body_size, kInt64Size) + desc.unwinding_info_size +
43 unwinding_info_size_field_size;
44 }
45 int object_size = Code::SizeFor(RoundUp(body_size, kObjectAlignment));
46 DCHECK(IsAligned(static_cast<intptr_t>(object_size), kCodeAlignment));
47 return object_size;
48 }
49
InitializeCode(Handle<Code> code,int object_size,const CodeDesc & desc,Code::Kind kind,Handle<Object> self_ref,int32_t builtin_index,Handle<ByteArray> source_position_table,Handle<DeoptimizationData> deopt_data,Handle<ByteArray> reloc_info,Handle<CodeDataContainer> data_container,uint32_t stub_key,bool is_turbofanned,int stack_slots,int safepoint_table_offset,int handler_table_offset)50 void InitializeCode(Handle<Code> code, int object_size, const CodeDesc& desc,
51 Code::Kind kind, Handle<Object> self_ref,
52 int32_t builtin_index,
53 Handle<ByteArray> source_position_table,
54 Handle<DeoptimizationData> deopt_data,
55 Handle<ByteArray> reloc_info,
56 Handle<CodeDataContainer> data_container, uint32_t stub_key,
57 bool is_turbofanned, int stack_slots,
58 int safepoint_table_offset, int handler_table_offset) {
59 DCHECK(IsAligned(code->address(), kCodeAlignment));
60 DCHECK(
61 !code->GetIsolate()->heap()->memory_allocator()->code_range()->valid() ||
62 code->GetIsolate()->heap()->memory_allocator()->code_range()->contains(
63 code->address()) ||
64 object_size <= code->GetIsolate()->heap()->code_space()->AreaSize());
65
66 bool has_unwinding_info = desc.unwinding_info != nullptr;
67
68 code->set_raw_instruction_size(desc.instr_size);
69 code->set_relocation_info(*reloc_info);
70 code->initialize_flags(kind, has_unwinding_info, is_turbofanned, stack_slots);
71 code->set_safepoint_table_offset(safepoint_table_offset);
72 code->set_handler_table_offset(handler_table_offset);
73 code->set_code_data_container(*data_container);
74 code->set_deoptimization_data(*deopt_data);
75 code->set_stub_key(stub_key);
76 code->set_source_position_table(*source_position_table);
77 code->set_constant_pool_offset(desc.instr_size - desc.constant_pool_size);
78 code->set_builtin_index(builtin_index);
79
80 // Allow self references to created code object by patching the handle to
81 // point to the newly allocated Code object.
82 if (!self_ref.is_null()) {
83 DCHECK(self_ref->IsOddball());
84 DCHECK(Oddball::cast(*self_ref)->kind() == Oddball::kSelfReferenceMarker);
85 #ifdef V8_EMBEDDED_BUILTINS
86 auto builder = code->GetIsolate()->builtins_constants_table_builder();
87 if (builder != nullptr) builder->PatchSelfReference(self_ref, code);
88 #endif // V8_EMBEDDED_BUILTINS
89 *(self_ref.location()) = *code;
90 }
91
92 // Migrate generated code.
93 // The generated code can contain Object** values (typically from handles)
94 // that are dereferenced during the copy to point directly to the actual heap
95 // objects. These pointers can include references to the code object itself,
96 // through the self_reference parameter.
97 code->CopyFromNoFlush(desc);
98
99 code->clear_padding();
100
101 #ifdef VERIFY_HEAP
102 if (FLAG_verify_heap) code->ObjectVerify();
103 #endif
104 }
105
106 } // namespace
107
AllocateRawWithImmortalMap(int size,PretenureFlag pretenure,Map * map,AllocationAlignment alignment)108 HeapObject* Factory::AllocateRawWithImmortalMap(int size,
109 PretenureFlag pretenure,
110 Map* map,
111 AllocationAlignment alignment) {
112 HeapObject* result = isolate()->heap()->AllocateRawWithRetryOrFail(
113 size, Heap::SelectSpace(pretenure), alignment);
114 result->set_map_after_allocation(map, SKIP_WRITE_BARRIER);
115 return result;
116 }
117
AllocateRawWithAllocationSite(Handle<Map> map,PretenureFlag pretenure,Handle<AllocationSite> allocation_site)118 HeapObject* Factory::AllocateRawWithAllocationSite(
119 Handle<Map> map, PretenureFlag pretenure,
120 Handle<AllocationSite> allocation_site) {
121 DCHECK(map->instance_type() != MAP_TYPE);
122 int size = map->instance_size();
123 if (!allocation_site.is_null()) size += AllocationMemento::kSize;
124 AllocationSpace space = Heap::SelectSpace(pretenure);
125 HeapObject* result =
126 isolate()->heap()->AllocateRawWithRetryOrFail(size, space);
127 WriteBarrierMode write_barrier_mode =
128 space == NEW_SPACE ? SKIP_WRITE_BARRIER : UPDATE_WRITE_BARRIER;
129 result->set_map_after_allocation(*map, write_barrier_mode);
130 if (!allocation_site.is_null()) {
131 AllocationMemento* alloc_memento = reinterpret_cast<AllocationMemento*>(
132 reinterpret_cast<Address>(result) + map->instance_size());
133 InitializeAllocationMemento(alloc_memento, *allocation_site);
134 }
135 return result;
136 }
137
InitializeAllocationMemento(AllocationMemento * memento,AllocationSite * allocation_site)138 void Factory::InitializeAllocationMemento(AllocationMemento* memento,
139 AllocationSite* allocation_site) {
140 memento->set_map_after_allocation(*allocation_memento_map(),
141 SKIP_WRITE_BARRIER);
142 DCHECK(allocation_site->map() == *allocation_site_map());
143 memento->set_allocation_site(allocation_site, SKIP_WRITE_BARRIER);
144 if (FLAG_allocation_site_pretenuring) {
145 allocation_site->IncrementMementoCreateCount();
146 }
147 }
148
AllocateRawArray(int size,PretenureFlag pretenure)149 HeapObject* Factory::AllocateRawArray(int size, PretenureFlag pretenure) {
150 AllocationSpace space = Heap::SelectSpace(pretenure);
151 HeapObject* result =
152 isolate()->heap()->AllocateRawWithRetryOrFail(size, space);
153 if (size > kMaxRegularHeapObjectSize && FLAG_use_marking_progress_bar) {
154 MemoryChunk* chunk = MemoryChunk::FromAddress(result->address());
155 chunk->SetFlag<AccessMode::ATOMIC>(MemoryChunk::HAS_PROGRESS_BAR);
156 }
157 return result;
158 }
159
AllocateRawFixedArray(int length,PretenureFlag pretenure)160 HeapObject* Factory::AllocateRawFixedArray(int length,
161 PretenureFlag pretenure) {
162 if (length < 0 || length > FixedArray::kMaxLength) {
163 isolate()->heap()->FatalProcessOutOfMemory("invalid array length");
164 }
165 return AllocateRawArray(FixedArray::SizeFor(length), pretenure);
166 }
167
AllocateRawWeakArrayList(int capacity,PretenureFlag pretenure)168 HeapObject* Factory::AllocateRawWeakArrayList(int capacity,
169 PretenureFlag pretenure) {
170 if (capacity < 0 || capacity > WeakArrayList::kMaxCapacity) {
171 isolate()->heap()->FatalProcessOutOfMemory("invalid array length");
172 }
173 return AllocateRawArray(WeakArrayList::SizeForCapacity(capacity), pretenure);
174 }
175
New(Handle<Map> map,PretenureFlag pretenure)176 HeapObject* Factory::New(Handle<Map> map, PretenureFlag pretenure) {
177 DCHECK(map->instance_type() != MAP_TYPE);
178 int size = map->instance_size();
179 AllocationSpace space = Heap::SelectSpace(pretenure);
180 HeapObject* result =
181 isolate()->heap()->AllocateRawWithRetryOrFail(size, space);
182 // New space objects are allocated white.
183 WriteBarrierMode write_barrier_mode =
184 space == NEW_SPACE ? SKIP_WRITE_BARRIER : UPDATE_WRITE_BARRIER;
185 result->set_map_after_allocation(*map, write_barrier_mode);
186 return result;
187 }
188
NewFillerObject(int size,bool double_align,AllocationSpace space)189 Handle<HeapObject> Factory::NewFillerObject(int size, bool double_align,
190 AllocationSpace space) {
191 AllocationAlignment alignment = double_align ? kDoubleAligned : kWordAligned;
192 Heap* heap = isolate()->heap();
193 HeapObject* result = heap->AllocateRawWithRetryOrFail(size, space, alignment);
194 #ifdef DEBUG
195 MemoryChunk* chunk = MemoryChunk::FromAddress(result->address());
196 DCHECK(chunk->owner()->identity() == space);
197 #endif
198 heap->CreateFillerObjectAt(result->address(), size, ClearRecordedSlots::kNo);
199 return Handle<HeapObject>(result, isolate());
200 }
201
NewPrototypeInfo()202 Handle<PrototypeInfo> Factory::NewPrototypeInfo() {
203 Handle<PrototypeInfo> result =
204 Handle<PrototypeInfo>::cast(NewStruct(PROTOTYPE_INFO_TYPE, TENURED));
205 result->set_prototype_users(FixedArrayOfWeakCells::Empty());
206 result->set_registry_slot(PrototypeInfo::UNREGISTERED);
207 result->set_bit_field(0);
208 return result;
209 }
210
NewEnumCache(Handle<FixedArray> keys,Handle<FixedArray> indices)211 Handle<EnumCache> Factory::NewEnumCache(Handle<FixedArray> keys,
212 Handle<FixedArray> indices) {
213 return Handle<EnumCache>::cast(NewTuple2(keys, indices, TENURED));
214 }
215
NewTuple2(Handle<Object> value1,Handle<Object> value2,PretenureFlag pretenure)216 Handle<Tuple2> Factory::NewTuple2(Handle<Object> value1, Handle<Object> value2,
217 PretenureFlag pretenure) {
218 Handle<Tuple2> result =
219 Handle<Tuple2>::cast(NewStruct(TUPLE2_TYPE, pretenure));
220 result->set_value1(*value1);
221 result->set_value2(*value2);
222 return result;
223 }
224
NewTuple3(Handle<Object> value1,Handle<Object> value2,Handle<Object> value3,PretenureFlag pretenure)225 Handle<Tuple3> Factory::NewTuple3(Handle<Object> value1, Handle<Object> value2,
226 Handle<Object> value3,
227 PretenureFlag pretenure) {
228 Handle<Tuple3> result =
229 Handle<Tuple3>::cast(NewStruct(TUPLE3_TYPE, pretenure));
230 result->set_value1(*value1);
231 result->set_value2(*value2);
232 result->set_value3(*value3);
233 return result;
234 }
235
NewConstantElementsPair(ElementsKind elements_kind,Handle<FixedArrayBase> constant_values)236 Handle<ConstantElementsPair> Factory::NewConstantElementsPair(
237 ElementsKind elements_kind, Handle<FixedArrayBase> constant_values) {
238 Handle<ConstantElementsPair> result =
239 Handle<ConstantElementsPair>::cast(NewStruct(TUPLE2_TYPE, TENURED));
240 result->set_elements_kind(elements_kind);
241 result->set_constant_values(*constant_values);
242 return result;
243 }
244
NewTemplateObjectDescription(Handle<FixedArray> raw_strings,Handle<FixedArray> cooked_strings)245 Handle<TemplateObjectDescription> Factory::NewTemplateObjectDescription(
246 Handle<FixedArray> raw_strings, Handle<FixedArray> cooked_strings) {
247 DCHECK_EQ(raw_strings->length(), cooked_strings->length());
248 DCHECK_LT(0, raw_strings->length());
249 Handle<TemplateObjectDescription> result =
250 Handle<TemplateObjectDescription>::cast(NewStruct(TUPLE2_TYPE, TENURED));
251 result->set_raw_strings(*raw_strings);
252 result->set_cooked_strings(*cooked_strings);
253 return result;
254 }
255
NewOddball(Handle<Map> map,const char * to_string,Handle<Object> to_number,const char * type_of,byte kind,PretenureFlag pretenure)256 Handle<Oddball> Factory::NewOddball(Handle<Map> map, const char* to_string,
257 Handle<Object> to_number,
258 const char* type_of, byte kind,
259 PretenureFlag pretenure) {
260 Handle<Oddball> oddball(Oddball::cast(New(map, pretenure)), isolate());
261 Oddball::Initialize(isolate(), oddball, to_string, to_number, type_of, kind);
262 return oddball;
263 }
264
NewSelfReferenceMarker(PretenureFlag pretenure)265 Handle<Oddball> Factory::NewSelfReferenceMarker(PretenureFlag pretenure) {
266 return NewOddball(self_reference_marker_map(), "self_reference_marker",
267 handle(Smi::FromInt(-1), isolate()), "undefined",
268 Oddball::kSelfReferenceMarker, pretenure);
269 }
270
NewPropertyArray(int length,PretenureFlag pretenure)271 Handle<PropertyArray> Factory::NewPropertyArray(int length,
272 PretenureFlag pretenure) {
273 DCHECK_LE(0, length);
274 if (length == 0) return empty_property_array();
275 HeapObject* result = AllocateRawFixedArray(length, pretenure);
276 result->set_map_after_allocation(*property_array_map(), SKIP_WRITE_BARRIER);
277 Handle<PropertyArray> array(PropertyArray::cast(result), isolate());
278 array->initialize_length(length);
279 MemsetPointer(array->data_start(), *undefined_value(), length);
280 return array;
281 }
282
NewFixedArrayWithFiller(Heap::RootListIndex map_root_index,int length,Object * filler,PretenureFlag pretenure)283 Handle<FixedArray> Factory::NewFixedArrayWithFiller(
284 Heap::RootListIndex map_root_index, int length, Object* filler,
285 PretenureFlag pretenure) {
286 HeapObject* result = AllocateRawFixedArray(length, pretenure);
287 DCHECK(Heap::RootIsImmortalImmovable(map_root_index));
288 Map* map = Map::cast(isolate()->heap()->root(map_root_index));
289 result->set_map_after_allocation(map, SKIP_WRITE_BARRIER);
290 Handle<FixedArray> array(FixedArray::cast(result), isolate());
291 array->set_length(length);
292 MemsetPointer(array->data_start(), filler, length);
293 return array;
294 }
295
296 template <typename T>
NewFixedArrayWithMap(Heap::RootListIndex map_root_index,int length,PretenureFlag pretenure)297 Handle<T> Factory::NewFixedArrayWithMap(Heap::RootListIndex map_root_index,
298 int length, PretenureFlag pretenure) {
299 static_assert(std::is_base_of<FixedArray, T>::value,
300 "T must be a descendant of FixedArray");
301 // Zero-length case must be handled outside, where the knowledge about
302 // the map is.
303 DCHECK_LT(0, length);
304 return Handle<T>::cast(NewFixedArrayWithFiller(
305 map_root_index, length, *undefined_value(), pretenure));
306 }
307
308 template <typename T>
NewWeakFixedArrayWithMap(Heap::RootListIndex map_root_index,int length,PretenureFlag pretenure)309 Handle<T> Factory::NewWeakFixedArrayWithMap(Heap::RootListIndex map_root_index,
310 int length,
311 PretenureFlag pretenure) {
312 static_assert(std::is_base_of<WeakFixedArray, T>::value,
313 "T must be a descendant of WeakFixedArray");
314
315 // Zero-length case must be handled outside.
316 DCHECK_LT(0, length);
317
318 HeapObject* result =
319 AllocateRawArray(WeakFixedArray::SizeFor(length), pretenure);
320 Map* map = Map::cast(isolate()->heap()->root(map_root_index));
321 result->set_map_after_allocation(map, SKIP_WRITE_BARRIER);
322
323 Handle<WeakFixedArray> array(WeakFixedArray::cast(result), isolate());
324 array->set_length(length);
325 MemsetPointer(array->data_start(),
326 HeapObjectReference::Strong(*undefined_value()), length);
327
328 return Handle<T>::cast(array);
329 }
330
331 template Handle<FixedArray> Factory::NewFixedArrayWithMap<FixedArray>(
332 Heap::RootListIndex, int, PretenureFlag);
333
NewFixedArray(int length,PretenureFlag pretenure)334 Handle<FixedArray> Factory::NewFixedArray(int length, PretenureFlag pretenure) {
335 DCHECK_LE(0, length);
336 if (length == 0) return empty_fixed_array();
337 return NewFixedArrayWithFiller(Heap::kFixedArrayMapRootIndex, length,
338 *undefined_value(), pretenure);
339 }
340
NewWeakFixedArray(int length,PretenureFlag pretenure)341 Handle<WeakFixedArray> Factory::NewWeakFixedArray(int length,
342 PretenureFlag pretenure) {
343 DCHECK_LE(0, length);
344 if (length == 0) return empty_weak_fixed_array();
345 HeapObject* result =
346 AllocateRawArray(WeakFixedArray::SizeFor(length), pretenure);
347 DCHECK(Heap::RootIsImmortalImmovable(Heap::kWeakFixedArrayMapRootIndex));
348 result->set_map_after_allocation(*weak_fixed_array_map(), SKIP_WRITE_BARRIER);
349 Handle<WeakFixedArray> array(WeakFixedArray::cast(result), isolate());
350 array->set_length(length);
351 MemsetPointer(array->data_start(),
352 HeapObjectReference::Strong(*undefined_value()), length);
353 return array;
354 }
355
TryNewFixedArray(int length,PretenureFlag pretenure)356 MaybeHandle<FixedArray> Factory::TryNewFixedArray(int length,
357 PretenureFlag pretenure) {
358 DCHECK_LE(0, length);
359 if (length == 0) return empty_fixed_array();
360
361 int size = FixedArray::SizeFor(length);
362 AllocationSpace space = Heap::SelectSpace(pretenure);
363 Heap* heap = isolate()->heap();
364 AllocationResult allocation = heap->AllocateRaw(size, space);
365 HeapObject* result = nullptr;
366 if (!allocation.To(&result)) return MaybeHandle<FixedArray>();
367 if (size > kMaxRegularHeapObjectSize && FLAG_use_marking_progress_bar) {
368 MemoryChunk* chunk = MemoryChunk::FromAddress(result->address());
369 chunk->SetFlag<AccessMode::ATOMIC>(MemoryChunk::HAS_PROGRESS_BAR);
370 }
371 result->set_map_after_allocation(*fixed_array_map(), SKIP_WRITE_BARRIER);
372 Handle<FixedArray> array(FixedArray::cast(result), isolate());
373 array->set_length(length);
374 MemsetPointer(array->data_start(), heap->undefined_value(), length);
375 return array;
376 }
377
NewFixedArrayWithHoles(int length,PretenureFlag pretenure)378 Handle<FixedArray> Factory::NewFixedArrayWithHoles(int length,
379 PretenureFlag pretenure) {
380 DCHECK_LE(0, length);
381 if (length == 0) return empty_fixed_array();
382 return NewFixedArrayWithFiller(Heap::kFixedArrayMapRootIndex, length,
383 *the_hole_value(), pretenure);
384 }
385
NewUninitializedFixedArray(int length,PretenureFlag pretenure)386 Handle<FixedArray> Factory::NewUninitializedFixedArray(
387 int length, PretenureFlag pretenure) {
388 DCHECK_LE(0, length);
389 if (length == 0) return empty_fixed_array();
390
391 // TODO(ulan): As an experiment this temporarily returns an initialized fixed
392 // array. After getting canary/performance coverage, either remove the
393 // function or revert to returning uninitilized array.
394 return NewFixedArrayWithFiller(Heap::kFixedArrayMapRootIndex, length,
395 *undefined_value(), pretenure);
396 }
397
NewFeedbackVector(Handle<SharedFunctionInfo> shared,PretenureFlag pretenure)398 Handle<FeedbackVector> Factory::NewFeedbackVector(
399 Handle<SharedFunctionInfo> shared, PretenureFlag pretenure) {
400 int length = shared->feedback_metadata()->slot_count();
401 DCHECK_LE(0, length);
402 int size = FeedbackVector::SizeFor(length);
403
404 HeapObject* result =
405 AllocateRawWithImmortalMap(size, pretenure, *feedback_vector_map());
406 Handle<FeedbackVector> vector(FeedbackVector::cast(result), isolate());
407 vector->set_shared_function_info(*shared);
408 vector->set_optimized_code_weak_or_smi(MaybeObject::FromSmi(Smi::FromEnum(
409 FLAG_log_function_events ? OptimizationMarker::kLogFirstExecution
410 : OptimizationMarker::kNone)));
411 vector->set_length(length);
412 vector->set_invocation_count(0);
413 vector->set_profiler_ticks(0);
414 vector->set_deopt_count(0);
415 // TODO(leszeks): Initialize based on the feedback metadata.
416 MemsetPointer(vector->slots_start(),
417 MaybeObject::FromObject(*undefined_value()), length);
418 return vector;
419 }
420
NewBoilerplateDescription(int boilerplate,int all_properties,int index_keys,bool has_seen_proto)421 Handle<BoilerplateDescription> Factory::NewBoilerplateDescription(
422 int boilerplate, int all_properties, int index_keys, bool has_seen_proto) {
423 DCHECK_GE(boilerplate, 0);
424 DCHECK_GE(all_properties, index_keys);
425 DCHECK_GE(index_keys, 0);
426
427 int backing_store_size =
428 all_properties - index_keys - (has_seen_proto ? 1 : 0);
429 DCHECK_GE(backing_store_size, 0);
430 bool has_different_size_backing_store = boilerplate != backing_store_size;
431
432 // Space for name and value for every boilerplate property.
433 int size = 2 * boilerplate;
434
435 if (has_different_size_backing_store) {
436 // An extra entry for the backing store size.
437 size++;
438 }
439
440 if (size == 0) {
441 return isolate()->factory()->empty_boilerplate_description();
442 }
443
444 Handle<BoilerplateDescription> description =
445 Handle<BoilerplateDescription>::cast(NewFixedArrayWithMap(
446 Heap::kBoilerplateDescriptionMapRootIndex, size, TENURED));
447
448 if (has_different_size_backing_store) {
449 DCHECK_IMPLIES((boilerplate == (all_properties - index_keys)),
450 has_seen_proto);
451 description->set_backing_store_size(isolate(), backing_store_size);
452 }
453
454 return description;
455 }
456
NewFixedDoubleArray(int length,PretenureFlag pretenure)457 Handle<FixedArrayBase> Factory::NewFixedDoubleArray(int length,
458 PretenureFlag pretenure) {
459 DCHECK_LE(0, length);
460 if (length == 0) return empty_fixed_array();
461 if (length > FixedDoubleArray::kMaxLength) {
462 isolate()->heap()->FatalProcessOutOfMemory("invalid array length");
463 }
464 int size = FixedDoubleArray::SizeFor(length);
465 Map* map = *fixed_double_array_map();
466 HeapObject* result =
467 AllocateRawWithImmortalMap(size, pretenure, map, kDoubleAligned);
468 Handle<FixedDoubleArray> array(FixedDoubleArray::cast(result), isolate());
469 array->set_length(length);
470 return array;
471 }
472
NewFixedDoubleArrayWithHoles(int length,PretenureFlag pretenure)473 Handle<FixedArrayBase> Factory::NewFixedDoubleArrayWithHoles(
474 int length, PretenureFlag pretenure) {
475 DCHECK_LE(0, length);
476 Handle<FixedArrayBase> array = NewFixedDoubleArray(length, pretenure);
477 if (length > 0) {
478 Handle<FixedDoubleArray>::cast(array)->FillWithHoles(0, length);
479 }
480 return array;
481 }
482
NewFeedbackMetadata(int slot_count,PretenureFlag tenure)483 Handle<FeedbackMetadata> Factory::NewFeedbackMetadata(int slot_count,
484 PretenureFlag tenure) {
485 DCHECK_LE(0, slot_count);
486 int size = FeedbackMetadata::SizeFor(slot_count);
487 HeapObject* result =
488 AllocateRawWithImmortalMap(size, tenure, *feedback_metadata_map());
489 Handle<FeedbackMetadata> data(FeedbackMetadata::cast(result), isolate());
490 data->set_slot_count(slot_count);
491
492 // Initialize the data section to 0.
493 int data_size = size - FeedbackMetadata::kHeaderSize;
494 Address data_start = data->address() + FeedbackMetadata::kHeaderSize;
495 memset(reinterpret_cast<byte*>(data_start), 0, data_size);
496 // Fields have been zeroed out but not initialized, so this object will not
497 // pass object verification at this point.
498 return data;
499 }
500
NewFrameArray(int number_of_frames,PretenureFlag pretenure)501 Handle<FrameArray> Factory::NewFrameArray(int number_of_frames,
502 PretenureFlag pretenure) {
503 DCHECK_LE(0, number_of_frames);
504 Handle<FixedArray> result = NewFixedArrayWithHoles(
505 FrameArray::LengthFor(number_of_frames), pretenure);
506 result->set(FrameArray::kFrameCountIndex, Smi::kZero);
507 return Handle<FrameArray>::cast(result);
508 }
509
NewSmallOrderedHashSet(int capacity,PretenureFlag pretenure)510 Handle<SmallOrderedHashSet> Factory::NewSmallOrderedHashSet(
511 int capacity, PretenureFlag pretenure) {
512 DCHECK_LE(0, capacity);
513 CHECK_LE(capacity, SmallOrderedHashSet::kMaxCapacity);
514 DCHECK_EQ(0, capacity % SmallOrderedHashSet::kLoadFactor);
515
516 int size = SmallOrderedHashSet::SizeFor(capacity);
517 Map* map = *small_ordered_hash_set_map();
518 HeapObject* result = AllocateRawWithImmortalMap(size, pretenure, map);
519 Handle<SmallOrderedHashSet> table(SmallOrderedHashSet::cast(result),
520 isolate());
521 table->Initialize(isolate(), capacity);
522 return table;
523 }
524
NewSmallOrderedHashMap(int capacity,PretenureFlag pretenure)525 Handle<SmallOrderedHashMap> Factory::NewSmallOrderedHashMap(
526 int capacity, PretenureFlag pretenure) {
527 DCHECK_LE(0, capacity);
528 CHECK_LE(capacity, SmallOrderedHashMap::kMaxCapacity);
529 DCHECK_EQ(0, capacity % SmallOrderedHashMap::kLoadFactor);
530
531 int size = SmallOrderedHashMap::SizeFor(capacity);
532 Map* map = *small_ordered_hash_map_map();
533 HeapObject* result = AllocateRawWithImmortalMap(size, pretenure, map);
534 Handle<SmallOrderedHashMap> table(SmallOrderedHashMap::cast(result),
535 isolate());
536 table->Initialize(isolate(), capacity);
537 return table;
538 }
539
NewOrderedHashSet()540 Handle<OrderedHashSet> Factory::NewOrderedHashSet() {
541 return OrderedHashSet::Allocate(isolate(), OrderedHashSet::kMinCapacity);
542 }
543
NewOrderedHashMap()544 Handle<OrderedHashMap> Factory::NewOrderedHashMap() {
545 return OrderedHashMap::Allocate(isolate(), OrderedHashMap::kMinCapacity);
546 }
547
NewAccessorPair()548 Handle<AccessorPair> Factory::NewAccessorPair() {
549 Handle<AccessorPair> accessors =
550 Handle<AccessorPair>::cast(NewStruct(ACCESSOR_PAIR_TYPE, TENURED));
551 accessors->set_getter(*null_value(), SKIP_WRITE_BARRIER);
552 accessors->set_setter(*null_value(), SKIP_WRITE_BARRIER);
553 return accessors;
554 }
555
556 // Internalized strings are created in the old generation (data space).
InternalizeUtf8String(Vector<const char> string)557 Handle<String> Factory::InternalizeUtf8String(Vector<const char> string) {
558 Utf8StringKey key(string, isolate()->heap()->HashSeed());
559 return InternalizeStringWithKey(&key);
560 }
561
InternalizeOneByteString(Vector<const uint8_t> string)562 Handle<String> Factory::InternalizeOneByteString(Vector<const uint8_t> string) {
563 OneByteStringKey key(string, isolate()->heap()->HashSeed());
564 return InternalizeStringWithKey(&key);
565 }
566
InternalizeOneByteString(Handle<SeqOneByteString> string,int from,int length)567 Handle<String> Factory::InternalizeOneByteString(
568 Handle<SeqOneByteString> string, int from, int length) {
569 SeqOneByteSubStringKey key(string, from, length);
570 return InternalizeStringWithKey(&key);
571 }
572
InternalizeTwoByteString(Vector<const uc16> string)573 Handle<String> Factory::InternalizeTwoByteString(Vector<const uc16> string) {
574 TwoByteStringKey key(string, isolate()->heap()->HashSeed());
575 return InternalizeStringWithKey(&key);
576 }
577
578 template <class StringTableKey>
InternalizeStringWithKey(StringTableKey * key)579 Handle<String> Factory::InternalizeStringWithKey(StringTableKey* key) {
580 return StringTable::LookupKey(isolate(), key);
581 }
582
NewStringFromOneByte(Vector<const uint8_t> string,PretenureFlag pretenure)583 MaybeHandle<String> Factory::NewStringFromOneByte(Vector<const uint8_t> string,
584 PretenureFlag pretenure) {
585 int length = string.length();
586 if (length == 0) return empty_string();
587 if (length == 1) return LookupSingleCharacterStringFromCode(string[0]);
588 Handle<SeqOneByteString> result;
589 ASSIGN_RETURN_ON_EXCEPTION(isolate(), result,
590 NewRawOneByteString(string.length(), pretenure),
591 String);
592
593 DisallowHeapAllocation no_gc;
594 // Copy the characters into the new object.
595 CopyChars(SeqOneByteString::cast(*result)->GetChars(), string.start(),
596 length);
597 return result;
598 }
599
NewStringFromUtf8(Vector<const char> string,PretenureFlag pretenure)600 MaybeHandle<String> Factory::NewStringFromUtf8(Vector<const char> string,
601 PretenureFlag pretenure) {
602 // Check for ASCII first since this is the common case.
603 const char* ascii_data = string.start();
604 int length = string.length();
605 int non_ascii_start = String::NonAsciiStart(ascii_data, length);
606 if (non_ascii_start >= length) {
607 // If the string is ASCII, we do not need to convert the characters
608 // since UTF8 is backwards compatible with ASCII.
609 return NewStringFromOneByte(Vector<const uint8_t>::cast(string), pretenure);
610 }
611
612 // Non-ASCII and we need to decode.
613 auto non_ascii = string.SubVector(non_ascii_start, length);
614 Access<UnicodeCache::Utf8Decoder> decoder(
615 isolate()->unicode_cache()->utf8_decoder());
616 decoder->Reset(non_ascii);
617
618 int utf16_length = static_cast<int>(decoder->Utf16Length());
619 DCHECK_GT(utf16_length, 0);
620
621 // Allocate string.
622 Handle<SeqTwoByteString> result;
623 ASSIGN_RETURN_ON_EXCEPTION(
624 isolate(), result,
625 NewRawTwoByteString(non_ascii_start + utf16_length, pretenure), String);
626
627 // Copy ASCII portion.
628 uint16_t* data = result->GetChars();
629 for (int i = 0; i < non_ascii_start; i++) {
630 *data++ = *ascii_data++;
631 }
632
633 // Now write the remainder.
634 decoder->WriteUtf16(data, utf16_length, non_ascii);
635 return result;
636 }
637
NewStringFromUtf8SubString(Handle<SeqOneByteString> str,int begin,int length,PretenureFlag pretenure)638 MaybeHandle<String> Factory::NewStringFromUtf8SubString(
639 Handle<SeqOneByteString> str, int begin, int length,
640 PretenureFlag pretenure) {
641 const char* ascii_data =
642 reinterpret_cast<const char*>(str->GetChars() + begin);
643 int non_ascii_start = String::NonAsciiStart(ascii_data, length);
644 if (non_ascii_start >= length) {
645 // If the string is ASCII, we can just make a substring.
646 // TODO(v8): the pretenure flag is ignored in this case.
647 return NewSubString(str, begin, begin + length);
648 }
649
650 // Non-ASCII and we need to decode.
651 auto non_ascii = Vector<const char>(ascii_data + non_ascii_start,
652 length - non_ascii_start);
653 Access<UnicodeCache::Utf8Decoder> decoder(
654 isolate()->unicode_cache()->utf8_decoder());
655 decoder->Reset(non_ascii);
656
657 int utf16_length = static_cast<int>(decoder->Utf16Length());
658 DCHECK_GT(utf16_length, 0);
659
660 // Allocate string.
661 Handle<SeqTwoByteString> result;
662 ASSIGN_RETURN_ON_EXCEPTION(
663 isolate(), result,
664 NewRawTwoByteString(non_ascii_start + utf16_length, pretenure), String);
665
666 // Update pointer references, since the original string may have moved after
667 // allocation.
668 ascii_data = reinterpret_cast<const char*>(str->GetChars() + begin);
669 non_ascii = Vector<const char>(ascii_data + non_ascii_start,
670 length - non_ascii_start);
671
672 // Copy ASCII portion.
673 uint16_t* data = result->GetChars();
674 for (int i = 0; i < non_ascii_start; i++) {
675 *data++ = *ascii_data++;
676 }
677
678 // Now write the remainder.
679 decoder->WriteUtf16(data, utf16_length, non_ascii);
680 return result;
681 }
682
NewStringFromTwoByte(const uc16 * string,int length,PretenureFlag pretenure)683 MaybeHandle<String> Factory::NewStringFromTwoByte(const uc16* string,
684 int length,
685 PretenureFlag pretenure) {
686 if (length == 0) return empty_string();
687 if (String::IsOneByte(string, length)) {
688 if (length == 1) return LookupSingleCharacterStringFromCode(string[0]);
689 Handle<SeqOneByteString> result;
690 ASSIGN_RETURN_ON_EXCEPTION(isolate(), result,
691 NewRawOneByteString(length, pretenure), String);
692 CopyChars(result->GetChars(), string, length);
693 return result;
694 } else {
695 Handle<SeqTwoByteString> result;
696 ASSIGN_RETURN_ON_EXCEPTION(isolate(), result,
697 NewRawTwoByteString(length, pretenure), String);
698 CopyChars(result->GetChars(), string, length);
699 return result;
700 }
701 }
702
NewStringFromTwoByte(Vector<const uc16> string,PretenureFlag pretenure)703 MaybeHandle<String> Factory::NewStringFromTwoByte(Vector<const uc16> string,
704 PretenureFlag pretenure) {
705 return NewStringFromTwoByte(string.start(), string.length(), pretenure);
706 }
707
NewStringFromTwoByte(const ZoneVector<uc16> * string,PretenureFlag pretenure)708 MaybeHandle<String> Factory::NewStringFromTwoByte(
709 const ZoneVector<uc16>* string, PretenureFlag pretenure) {
710 return NewStringFromTwoByte(string->data(), static_cast<int>(string->size()),
711 pretenure);
712 }
713
714 namespace {
715
IsOneByte(Vector<const char> str,int chars)716 bool inline IsOneByte(Vector<const char> str, int chars) {
717 // TODO(dcarney): incorporate Latin-1 check when Latin-1 is supported?
718 return chars == str.length();
719 }
720
IsOneByte(Handle<String> str)721 bool inline IsOneByte(Handle<String> str) {
722 return str->IsOneByteRepresentation();
723 }
724
WriteOneByteData(Vector<const char> vector,uint8_t * chars,int len)725 inline void WriteOneByteData(Vector<const char> vector, uint8_t* chars,
726 int len) {
727 // Only works for one byte strings.
728 DCHECK(vector.length() == len);
729 MemCopy(chars, vector.start(), len);
730 }
731
WriteTwoByteData(Vector<const char> vector,uint16_t * chars,int len)732 inline void WriteTwoByteData(Vector<const char> vector, uint16_t* chars,
733 int len) {
734 unibrow::Utf8Iterator it = unibrow::Utf8Iterator(vector);
735 while (!it.Done()) {
736 DCHECK_GT(len, 0);
737 len -= 1;
738
739 uint16_t c = *it;
740 ++it;
741 DCHECK_NE(unibrow::Utf8::kBadChar, c);
742 *chars++ = c;
743 }
744 DCHECK_EQ(len, 0);
745 }
746
WriteOneByteData(Handle<String> s,uint8_t * chars,int len)747 inline void WriteOneByteData(Handle<String> s, uint8_t* chars, int len) {
748 DCHECK(s->length() == len);
749 String::WriteToFlat(*s, chars, 0, len);
750 }
751
WriteTwoByteData(Handle<String> s,uint16_t * chars,int len)752 inline void WriteTwoByteData(Handle<String> s, uint16_t* chars, int len) {
753 DCHECK(s->length() == len);
754 String::WriteToFlat(*s, chars, 0, len);
755 }
756
757 } // namespace
758
AllocateRawOneByteInternalizedString(int length,uint32_t hash_field)759 Handle<SeqOneByteString> Factory::AllocateRawOneByteInternalizedString(
760 int length, uint32_t hash_field) {
761 CHECK_GE(String::kMaxLength, length);
762 // The canonical empty_string is the only zero-length string we allow.
763 DCHECK_IMPLIES(
764 length == 0,
765 isolate()->heap()->roots_[Heap::kempty_stringRootIndex] == nullptr);
766
767 Map* map = *one_byte_internalized_string_map();
768 int size = SeqOneByteString::SizeFor(length);
769 HeapObject* result = AllocateRawWithImmortalMap(
770 size,
771 isolate()->heap()->CanAllocateInReadOnlySpace() ? TENURED_READ_ONLY
772 : TENURED,
773 map);
774 Handle<SeqOneByteString> answer(SeqOneByteString::cast(result), isolate());
775 answer->set_length(length);
776 answer->set_hash_field(hash_field);
777 DCHECK_EQ(size, answer->Size());
778 return answer;
779 }
780
AllocateTwoByteInternalizedString(Vector<const uc16> str,uint32_t hash_field)781 Handle<String> Factory::AllocateTwoByteInternalizedString(
782 Vector<const uc16> str, uint32_t hash_field) {
783 CHECK_GE(String::kMaxLength, str.length());
784 DCHECK_NE(0, str.length()); // Use Heap::empty_string() instead.
785
786 Map* map = *internalized_string_map();
787 int size = SeqTwoByteString::SizeFor(str.length());
788 HeapObject* result = AllocateRawWithImmortalMap(size, TENURED, map);
789 Handle<SeqTwoByteString> answer(SeqTwoByteString::cast(result), isolate());
790 answer->set_length(str.length());
791 answer->set_hash_field(hash_field);
792 DCHECK_EQ(size, answer->Size());
793
794 // Fill in the characters.
795 MemCopy(answer->GetChars(), str.start(), str.length() * kUC16Size);
796
797 return answer;
798 }
799
800 template <bool is_one_byte, typename T>
AllocateInternalizedStringImpl(T t,int chars,uint32_t hash_field)801 Handle<String> Factory::AllocateInternalizedStringImpl(T t, int chars,
802 uint32_t hash_field) {
803 DCHECK_LE(0, chars);
804 DCHECK_GE(String::kMaxLength, chars);
805
806 // Compute map and object size.
807 int size;
808 Map* map;
809 if (is_one_byte) {
810 map = *one_byte_internalized_string_map();
811 size = SeqOneByteString::SizeFor(chars);
812 } else {
813 map = *internalized_string_map();
814 size = SeqTwoByteString::SizeFor(chars);
815 }
816
817 HeapObject* result = AllocateRawWithImmortalMap(
818 size,
819 isolate()->heap()->CanAllocateInReadOnlySpace() ? TENURED_READ_ONLY
820 : TENURED,
821 map);
822 Handle<String> answer(String::cast(result), isolate());
823 answer->set_length(chars);
824 answer->set_hash_field(hash_field);
825 DCHECK_EQ(size, answer->Size());
826
827 if (is_one_byte) {
828 WriteOneByteData(t, SeqOneByteString::cast(*answer)->GetChars(), chars);
829 } else {
830 WriteTwoByteData(t, SeqTwoByteString::cast(*answer)->GetChars(), chars);
831 }
832 return answer;
833 }
834
NewInternalizedStringFromUtf8(Vector<const char> str,int chars,uint32_t hash_field)835 Handle<String> Factory::NewInternalizedStringFromUtf8(Vector<const char> str,
836 int chars,
837 uint32_t hash_field) {
838 if (IsOneByte(str, chars)) {
839 Handle<SeqOneByteString> result =
840 AllocateRawOneByteInternalizedString(str.length(), hash_field);
841 MemCopy(result->GetChars(), str.start(), str.length());
842 return result;
843 }
844 return AllocateInternalizedStringImpl<false>(str, chars, hash_field);
845 }
846
NewOneByteInternalizedString(Vector<const uint8_t> str,uint32_t hash_field)847 Handle<String> Factory::NewOneByteInternalizedString(Vector<const uint8_t> str,
848 uint32_t hash_field) {
849 Handle<SeqOneByteString> result =
850 AllocateRawOneByteInternalizedString(str.length(), hash_field);
851 MemCopy(result->GetChars(), str.start(), str.length());
852 return result;
853 }
854
NewOneByteInternalizedSubString(Handle<SeqOneByteString> string,int offset,int length,uint32_t hash_field)855 Handle<String> Factory::NewOneByteInternalizedSubString(
856 Handle<SeqOneByteString> string, int offset, int length,
857 uint32_t hash_field) {
858 Handle<SeqOneByteString> result =
859 AllocateRawOneByteInternalizedString(length, hash_field);
860 MemCopy(result->GetChars(), string->GetChars() + offset, length);
861 return result;
862 }
863
NewTwoByteInternalizedString(Vector<const uc16> str,uint32_t hash_field)864 Handle<String> Factory::NewTwoByteInternalizedString(Vector<const uc16> str,
865 uint32_t hash_field) {
866 return AllocateTwoByteInternalizedString(str, hash_field);
867 }
868
NewInternalizedStringImpl(Handle<String> string,int chars,uint32_t hash_field)869 Handle<String> Factory::NewInternalizedStringImpl(Handle<String> string,
870 int chars,
871 uint32_t hash_field) {
872 if (IsOneByte(string)) {
873 return AllocateInternalizedStringImpl<true>(string, chars, hash_field);
874 }
875 return AllocateInternalizedStringImpl<false>(string, chars, hash_field);
876 }
877
878 namespace {
879
GetInternalizedStringMap(Factory * f,Handle<String> string)880 MaybeHandle<Map> GetInternalizedStringMap(Factory* f, Handle<String> string) {
881 switch (string->map()->instance_type()) {
882 case STRING_TYPE:
883 return f->internalized_string_map();
884 case ONE_BYTE_STRING_TYPE:
885 return f->one_byte_internalized_string_map();
886 case EXTERNAL_STRING_TYPE:
887 return f->external_internalized_string_map();
888 case EXTERNAL_ONE_BYTE_STRING_TYPE:
889 return f->external_one_byte_internalized_string_map();
890 case EXTERNAL_STRING_WITH_ONE_BYTE_DATA_TYPE:
891 return f->external_internalized_string_with_one_byte_data_map();
892 case SHORT_EXTERNAL_STRING_TYPE:
893 return f->short_external_internalized_string_map();
894 case SHORT_EXTERNAL_ONE_BYTE_STRING_TYPE:
895 return f->short_external_one_byte_internalized_string_map();
896 case SHORT_EXTERNAL_STRING_WITH_ONE_BYTE_DATA_TYPE:
897 return f->short_external_internalized_string_with_one_byte_data_map();
898 default:
899 return MaybeHandle<Map>(); // No match found.
900 }
901 }
902
903 } // namespace
904
InternalizedStringMapForString(Handle<String> string)905 MaybeHandle<Map> Factory::InternalizedStringMapForString(
906 Handle<String> string) {
907 // If the string is in new space it cannot be used as internalized.
908 if (isolate()->heap()->InNewSpace(*string)) return MaybeHandle<Map>();
909
910 return GetInternalizedStringMap(this, string);
911 }
912
913 template <class StringClass>
InternalizeExternalString(Handle<String> string)914 Handle<StringClass> Factory::InternalizeExternalString(Handle<String> string) {
915 Handle<StringClass> cast_string = Handle<StringClass>::cast(string);
916 Handle<Map> map = GetInternalizedStringMap(this, string).ToHandleChecked();
917 Handle<StringClass> external_string(StringClass::cast(New(map, TENURED)),
918 isolate());
919 external_string->set_length(cast_string->length());
920 external_string->set_hash_field(cast_string->hash_field());
921 external_string->set_resource(nullptr);
922 isolate()->heap()->RegisterExternalString(*external_string);
923 return external_string;
924 }
925
926 template Handle<ExternalOneByteString>
927 Factory::InternalizeExternalString<ExternalOneByteString>(Handle<String>);
928 template Handle<ExternalTwoByteString>
929 Factory::InternalizeExternalString<ExternalTwoByteString>(Handle<String>);
930
NewRawOneByteString(int length,PretenureFlag pretenure)931 MaybeHandle<SeqOneByteString> Factory::NewRawOneByteString(
932 int length, PretenureFlag pretenure) {
933 if (length > String::kMaxLength || length < 0) {
934 THROW_NEW_ERROR(isolate(), NewInvalidStringLengthError(), SeqOneByteString);
935 }
936 DCHECK_GT(length, 0); // Use Factory::empty_string() instead.
937 int size = SeqOneByteString::SizeFor(length);
938 DCHECK_GE(SeqOneByteString::kMaxSize, size);
939
940 HeapObject* result =
941 AllocateRawWithImmortalMap(size, pretenure, *one_byte_string_map());
942 Handle<SeqOneByteString> string(SeqOneByteString::cast(result), isolate());
943 string->set_length(length);
944 string->set_hash_field(String::kEmptyHashField);
945 DCHECK_EQ(size, string->Size());
946 return string;
947 }
948
NewRawTwoByteString(int length,PretenureFlag pretenure)949 MaybeHandle<SeqTwoByteString> Factory::NewRawTwoByteString(
950 int length, PretenureFlag pretenure) {
951 if (length > String::kMaxLength || length < 0) {
952 THROW_NEW_ERROR(isolate(), NewInvalidStringLengthError(), SeqTwoByteString);
953 }
954 DCHECK_GT(length, 0); // Use Factory::empty_string() instead.
955 int size = SeqTwoByteString::SizeFor(length);
956 DCHECK_GE(SeqTwoByteString::kMaxSize, size);
957
958 HeapObject* result =
959 AllocateRawWithImmortalMap(size, pretenure, *string_map());
960 Handle<SeqTwoByteString> string(SeqTwoByteString::cast(result), isolate());
961 string->set_length(length);
962 string->set_hash_field(String::kEmptyHashField);
963 DCHECK_EQ(size, string->Size());
964 return string;
965 }
966
LookupSingleCharacterStringFromCode(uint32_t code)967 Handle<String> Factory::LookupSingleCharacterStringFromCode(uint32_t code) {
968 if (code <= String::kMaxOneByteCharCodeU) {
969 {
970 DisallowHeapAllocation no_allocation;
971 Object* value = single_character_string_cache()->get(code);
972 if (value != *undefined_value()) {
973 return handle(String::cast(value), isolate());
974 }
975 }
976 uint8_t buffer[1];
977 buffer[0] = static_cast<uint8_t>(code);
978 Handle<String> result =
979 InternalizeOneByteString(Vector<const uint8_t>(buffer, 1));
980 single_character_string_cache()->set(code, *result);
981 return result;
982 }
983 DCHECK_LE(code, String::kMaxUtf16CodeUnitU);
984
985 Handle<SeqTwoByteString> result = NewRawTwoByteString(1).ToHandleChecked();
986 result->SeqTwoByteStringSet(0, static_cast<uint16_t>(code));
987 return result;
988 }
989
990 // Returns true for a character in a range. Both limits are inclusive.
Between(uint32_t character,uint32_t from,uint32_t to)991 static inline bool Between(uint32_t character, uint32_t from, uint32_t to) {
992 // This makes uses of the the unsigned wraparound.
993 return character - from <= to - from;
994 }
995
MakeOrFindTwoCharacterString(Isolate * isolate,uint16_t c1,uint16_t c2)996 static inline Handle<String> MakeOrFindTwoCharacterString(Isolate* isolate,
997 uint16_t c1,
998 uint16_t c2) {
999 // Numeric strings have a different hash algorithm not known by
1000 // LookupTwoCharsStringIfExists, so we skip this step for such strings.
1001 if (!Between(c1, '0', '9') || !Between(c2, '0', '9')) {
1002 Handle<String> result;
1003 if (StringTable::LookupTwoCharsStringIfExists(isolate, c1, c2)
1004 .ToHandle(&result)) {
1005 return result;
1006 }
1007 }
1008
1009 // Now we know the length is 2, we might as well make use of that fact
1010 // when building the new string.
1011 if (static_cast<unsigned>(c1 | c2) <= String::kMaxOneByteCharCodeU) {
1012 // We can do this.
1013 DCHECK(base::bits::IsPowerOfTwo(String::kMaxOneByteCharCodeU +
1014 1)); // because of this.
1015 Handle<SeqOneByteString> str =
1016 isolate->factory()->NewRawOneByteString(2).ToHandleChecked();
1017 uint8_t* dest = str->GetChars();
1018 dest[0] = static_cast<uint8_t>(c1);
1019 dest[1] = static_cast<uint8_t>(c2);
1020 return str;
1021 } else {
1022 Handle<SeqTwoByteString> str =
1023 isolate->factory()->NewRawTwoByteString(2).ToHandleChecked();
1024 uc16* dest = str->GetChars();
1025 dest[0] = c1;
1026 dest[1] = c2;
1027 return str;
1028 }
1029 }
1030
1031 template <typename SinkChar, typename StringType>
ConcatStringContent(Handle<StringType> result,Handle<String> first,Handle<String> second)1032 Handle<String> ConcatStringContent(Handle<StringType> result,
1033 Handle<String> first,
1034 Handle<String> second) {
1035 DisallowHeapAllocation pointer_stays_valid;
1036 SinkChar* sink = result->GetChars();
1037 String::WriteToFlat(*first, sink, 0, first->length());
1038 String::WriteToFlat(*second, sink + first->length(), 0, second->length());
1039 return result;
1040 }
1041
NewConsString(Handle<String> left,Handle<String> right)1042 MaybeHandle<String> Factory::NewConsString(Handle<String> left,
1043 Handle<String> right) {
1044 if (left->IsThinString()) {
1045 left = handle(Handle<ThinString>::cast(left)->actual(), isolate());
1046 }
1047 if (right->IsThinString()) {
1048 right = handle(Handle<ThinString>::cast(right)->actual(), isolate());
1049 }
1050 int left_length = left->length();
1051 if (left_length == 0) return right;
1052 int right_length = right->length();
1053 if (right_length == 0) return left;
1054
1055 int length = left_length + right_length;
1056
1057 if (length == 2) {
1058 uint16_t c1 = left->Get(0);
1059 uint16_t c2 = right->Get(0);
1060 return MakeOrFindTwoCharacterString(isolate(), c1, c2);
1061 }
1062
1063 // Make sure that an out of memory exception is thrown if the length
1064 // of the new cons string is too large.
1065 if (length > String::kMaxLength || length < 0) {
1066 THROW_NEW_ERROR(isolate(), NewInvalidStringLengthError(), String);
1067 }
1068
1069 bool left_is_one_byte = left->IsOneByteRepresentation();
1070 bool right_is_one_byte = right->IsOneByteRepresentation();
1071 bool is_one_byte = left_is_one_byte && right_is_one_byte;
1072 bool is_one_byte_data_in_two_byte_string = false;
1073 if (!is_one_byte) {
1074 // At least one of the strings uses two-byte representation so we
1075 // can't use the fast case code for short one-byte strings below, but
1076 // we can try to save memory if all chars actually fit in one-byte.
1077 is_one_byte_data_in_two_byte_string =
1078 left->HasOnlyOneByteChars() && right->HasOnlyOneByteChars();
1079 if (is_one_byte_data_in_two_byte_string) {
1080 isolate()->counters()->string_add_runtime_ext_to_one_byte()->Increment();
1081 }
1082 }
1083
1084 // If the resulting string is small make a flat string.
1085 if (length < ConsString::kMinLength) {
1086 // Note that neither of the two inputs can be a slice because:
1087 STATIC_ASSERT(ConsString::kMinLength <= SlicedString::kMinLength);
1088 DCHECK(left->IsFlat());
1089 DCHECK(right->IsFlat());
1090
1091 STATIC_ASSERT(ConsString::kMinLength <= String::kMaxLength);
1092 if (is_one_byte) {
1093 Handle<SeqOneByteString> result =
1094 NewRawOneByteString(length).ToHandleChecked();
1095 DisallowHeapAllocation no_gc;
1096 uint8_t* dest = result->GetChars();
1097 // Copy left part.
1098 const uint8_t* src =
1099 left->IsExternalString()
1100 ? Handle<ExternalOneByteString>::cast(left)->GetChars()
1101 : Handle<SeqOneByteString>::cast(left)->GetChars();
1102 for (int i = 0; i < left_length; i++) *dest++ = src[i];
1103 // Copy right part.
1104 src = right->IsExternalString()
1105 ? Handle<ExternalOneByteString>::cast(right)->GetChars()
1106 : Handle<SeqOneByteString>::cast(right)->GetChars();
1107 for (int i = 0; i < right_length; i++) *dest++ = src[i];
1108 return result;
1109 }
1110
1111 return (is_one_byte_data_in_two_byte_string)
1112 ? ConcatStringContent<uint8_t>(
1113 NewRawOneByteString(length).ToHandleChecked(), left, right)
1114 : ConcatStringContent<uc16>(
1115 NewRawTwoByteString(length).ToHandleChecked(), left,
1116 right);
1117 }
1118
1119 bool one_byte = (is_one_byte || is_one_byte_data_in_two_byte_string);
1120 return NewConsString(left, right, length, one_byte);
1121 }
1122
NewConsString(Handle<String> left,Handle<String> right,int length,bool one_byte)1123 Handle<String> Factory::NewConsString(Handle<String> left, Handle<String> right,
1124 int length, bool one_byte) {
1125 DCHECK(!left->IsThinString());
1126 DCHECK(!right->IsThinString());
1127 DCHECK_GE(length, ConsString::kMinLength);
1128 DCHECK_LE(length, String::kMaxLength);
1129
1130 Handle<ConsString> result(
1131 ConsString::cast(one_byte ? New(cons_one_byte_string_map(), NOT_TENURED)
1132 : New(cons_string_map(), NOT_TENURED)),
1133 isolate());
1134
1135 DisallowHeapAllocation no_gc;
1136 WriteBarrierMode mode = result->GetWriteBarrierMode(no_gc);
1137
1138 result->set_hash_field(String::kEmptyHashField);
1139 result->set_length(length);
1140 result->set_first(*left, mode);
1141 result->set_second(*right, mode);
1142 return result;
1143 }
1144
NewSurrogatePairString(uint16_t lead,uint16_t trail)1145 Handle<String> Factory::NewSurrogatePairString(uint16_t lead, uint16_t trail) {
1146 DCHECK_GE(lead, 0xD800);
1147 DCHECK_LE(lead, 0xDBFF);
1148 DCHECK_GE(trail, 0xDC00);
1149 DCHECK_LE(trail, 0xDFFF);
1150
1151 Handle<SeqTwoByteString> str =
1152 isolate()->factory()->NewRawTwoByteString(2).ToHandleChecked();
1153 uc16* dest = str->GetChars();
1154 dest[0] = lead;
1155 dest[1] = trail;
1156 return str;
1157 }
1158
NewProperSubString(Handle<String> str,int begin,int end)1159 Handle<String> Factory::NewProperSubString(Handle<String> str, int begin,
1160 int end) {
1161 #if VERIFY_HEAP
1162 if (FLAG_verify_heap) str->StringVerify();
1163 #endif
1164 DCHECK(begin > 0 || end < str->length());
1165
1166 str = String::Flatten(str);
1167
1168 int length = end - begin;
1169 if (length <= 0) return empty_string();
1170 if (length == 1) {
1171 return LookupSingleCharacterStringFromCode(str->Get(begin));
1172 }
1173 if (length == 2) {
1174 // Optimization for 2-byte strings often used as keys in a decompression
1175 // dictionary. Check whether we already have the string in the string
1176 // table to prevent creation of many unnecessary strings.
1177 uint16_t c1 = str->Get(begin);
1178 uint16_t c2 = str->Get(begin + 1);
1179 return MakeOrFindTwoCharacterString(isolate(), c1, c2);
1180 }
1181
1182 if (!FLAG_string_slices || length < SlicedString::kMinLength) {
1183 if (str->IsOneByteRepresentation()) {
1184 Handle<SeqOneByteString> result =
1185 NewRawOneByteString(length).ToHandleChecked();
1186 uint8_t* dest = result->GetChars();
1187 DisallowHeapAllocation no_gc;
1188 String::WriteToFlat(*str, dest, begin, end);
1189 return result;
1190 } else {
1191 Handle<SeqTwoByteString> result =
1192 NewRawTwoByteString(length).ToHandleChecked();
1193 uc16* dest = result->GetChars();
1194 DisallowHeapAllocation no_gc;
1195 String::WriteToFlat(*str, dest, begin, end);
1196 return result;
1197 }
1198 }
1199
1200 int offset = begin;
1201
1202 if (str->IsSlicedString()) {
1203 Handle<SlicedString> slice = Handle<SlicedString>::cast(str);
1204 str = Handle<String>(slice->parent(), isolate());
1205 offset += slice->offset();
1206 }
1207 if (str->IsThinString()) {
1208 Handle<ThinString> thin = Handle<ThinString>::cast(str);
1209 str = handle(thin->actual(), isolate());
1210 }
1211
1212 DCHECK(str->IsSeqString() || str->IsExternalString());
1213 Handle<Map> map = str->IsOneByteRepresentation()
1214 ? sliced_one_byte_string_map()
1215 : sliced_string_map();
1216 Handle<SlicedString> slice(SlicedString::cast(New(map, NOT_TENURED)),
1217 isolate());
1218
1219 slice->set_hash_field(String::kEmptyHashField);
1220 slice->set_length(length);
1221 slice->set_parent(*str);
1222 slice->set_offset(offset);
1223 return slice;
1224 }
1225
NewExternalStringFromOneByte(const ExternalOneByteString::Resource * resource)1226 MaybeHandle<String> Factory::NewExternalStringFromOneByte(
1227 const ExternalOneByteString::Resource* resource) {
1228 size_t length = resource->length();
1229 if (length > static_cast<size_t>(String::kMaxLength)) {
1230 THROW_NEW_ERROR(isolate(), NewInvalidStringLengthError(), String);
1231 }
1232 if (length == 0) return empty_string();
1233
1234 Handle<Map> map;
1235 if (resource->IsCompressible()) {
1236 // TODO(hajimehoshi): Rename this to 'uncached_external_one_byte_string_map'
1237 map = short_external_one_byte_string_map();
1238 } else {
1239 map = external_one_byte_string_map();
1240 }
1241 Handle<ExternalOneByteString> external_string(
1242 ExternalOneByteString::cast(New(map, TENURED)), isolate());
1243 external_string->set_length(static_cast<int>(length));
1244 external_string->set_hash_field(String::kEmptyHashField);
1245 external_string->set_resource(resource);
1246
1247 return external_string;
1248 }
1249
NewExternalStringFromTwoByte(const ExternalTwoByteString::Resource * resource)1250 MaybeHandle<String> Factory::NewExternalStringFromTwoByte(
1251 const ExternalTwoByteString::Resource* resource) {
1252 size_t length = resource->length();
1253 if (length > static_cast<size_t>(String::kMaxLength)) {
1254 THROW_NEW_ERROR(isolate(), NewInvalidStringLengthError(), String);
1255 }
1256 if (length == 0) return empty_string();
1257
1258 // For small strings we check whether the resource contains only
1259 // one byte characters. If yes, we use a different string map.
1260 static const size_t kOneByteCheckLengthLimit = 32;
1261 bool is_one_byte =
1262 length <= kOneByteCheckLengthLimit &&
1263 String::IsOneByte(resource->data(), static_cast<int>(length));
1264 Handle<Map> map;
1265 if (resource->IsCompressible()) {
1266 // TODO(hajimehoshi): Rename these to 'uncached_external_string_...'.
1267 map = is_one_byte ? short_external_string_with_one_byte_data_map()
1268 : short_external_string_map();
1269 } else {
1270 map = is_one_byte ? external_string_with_one_byte_data_map()
1271 : external_string_map();
1272 }
1273 Handle<ExternalTwoByteString> external_string(
1274 ExternalTwoByteString::cast(New(map, TENURED)), isolate());
1275 external_string->set_length(static_cast<int>(length));
1276 external_string->set_hash_field(String::kEmptyHashField);
1277 external_string->set_resource(resource);
1278
1279 return external_string;
1280 }
1281
NewNativeSourceString(const ExternalOneByteString::Resource * resource)1282 Handle<ExternalOneByteString> Factory::NewNativeSourceString(
1283 const ExternalOneByteString::Resource* resource) {
1284 size_t length = resource->length();
1285 DCHECK_LE(length, static_cast<size_t>(String::kMaxLength));
1286
1287 Handle<Map> map = native_source_string_map();
1288 Handle<ExternalOneByteString> external_string(
1289 ExternalOneByteString::cast(New(map, TENURED)), isolate());
1290 external_string->set_length(static_cast<int>(length));
1291 external_string->set_hash_field(String::kEmptyHashField);
1292 external_string->set_resource(resource);
1293
1294 return external_string;
1295 }
1296
NewJSStringIterator(Handle<String> string)1297 Handle<JSStringIterator> Factory::NewJSStringIterator(Handle<String> string) {
1298 Handle<Map> map(isolate()->native_context()->string_iterator_map(),
1299 isolate());
1300 Handle<String> flat_string = String::Flatten(string);
1301 Handle<JSStringIterator> iterator =
1302 Handle<JSStringIterator>::cast(NewJSObjectFromMap(map));
1303 iterator->set_string(*flat_string);
1304 iterator->set_index(0);
1305
1306 return iterator;
1307 }
1308
NewSymbol(PretenureFlag flag)1309 Handle<Symbol> Factory::NewSymbol(PretenureFlag flag) {
1310 DCHECK(flag != NOT_TENURED);
1311 // Statically ensure that it is safe to allocate symbols in paged spaces.
1312 STATIC_ASSERT(Symbol::kSize <= kMaxRegularHeapObjectSize);
1313
1314 HeapObject* result =
1315 AllocateRawWithImmortalMap(Symbol::kSize, flag, *symbol_map());
1316
1317 // Generate a random hash value.
1318 int hash = isolate()->GenerateIdentityHash(Name::kHashBitMask);
1319
1320 Handle<Symbol> symbol(Symbol::cast(result), isolate());
1321 symbol->set_hash_field(Name::kIsNotArrayIndexMask |
1322 (hash << Name::kHashShift));
1323 symbol->set_name(*undefined_value());
1324 symbol->set_flags(0);
1325 DCHECK(!symbol->is_private());
1326 return symbol;
1327 }
1328
NewPrivateSymbol(PretenureFlag flag)1329 Handle<Symbol> Factory::NewPrivateSymbol(PretenureFlag flag) {
1330 DCHECK(flag != NOT_TENURED);
1331 Handle<Symbol> symbol = NewSymbol(flag);
1332 symbol->set_is_private(true);
1333 return symbol;
1334 }
1335
NewPrivateFieldSymbol()1336 Handle<Symbol> Factory::NewPrivateFieldSymbol() {
1337 Handle<Symbol> symbol = NewSymbol();
1338 symbol->set_is_private_field();
1339 return symbol;
1340 }
1341
NewNativeContext()1342 Handle<Context> Factory::NewNativeContext() {
1343 Handle<Context> context = NewFixedArrayWithMap<Context>(
1344 Heap::kNativeContextMapRootIndex, Context::NATIVE_CONTEXT_SLOTS, TENURED);
1345 context->set_native_context(*context);
1346 context->set_errors_thrown(Smi::kZero);
1347 context->set_math_random_index(Smi::kZero);
1348 Handle<WeakCell> weak_cell = NewWeakCell(context);
1349 context->set_self_weak_cell(*weak_cell);
1350 context->set_serialized_objects(*empty_fixed_array());
1351 DCHECK(context->IsNativeContext());
1352 return context;
1353 }
1354
NewScriptContext(Handle<Context> outer,Handle<ScopeInfo> scope_info)1355 Handle<Context> Factory::NewScriptContext(Handle<Context> outer,
1356 Handle<ScopeInfo> scope_info) {
1357 DCHECK_EQ(scope_info->scope_type(), SCRIPT_SCOPE);
1358 DCHECK(outer->IsNativeContext());
1359 Handle<Context> context = NewFixedArrayWithMap<Context>(
1360 Heap::kScriptContextMapRootIndex, scope_info->ContextLength(), TENURED);
1361 context->set_scope_info(*scope_info);
1362 context->set_previous(*outer);
1363 context->set_extension(*the_hole_value());
1364 context->set_native_context(*outer);
1365 DCHECK(context->IsScriptContext());
1366 return context;
1367 }
1368
NewScriptContextTable()1369 Handle<ScriptContextTable> Factory::NewScriptContextTable() {
1370 Handle<ScriptContextTable> context_table =
1371 NewFixedArrayWithMap<ScriptContextTable>(
1372 Heap::kScriptContextTableMapRootIndex,
1373 ScriptContextTable::kMinLength);
1374 context_table->set_used(0);
1375 return context_table;
1376 }
1377
NewModuleContext(Handle<Module> module,Handle<Context> outer,Handle<ScopeInfo> scope_info)1378 Handle<Context> Factory::NewModuleContext(Handle<Module> module,
1379 Handle<Context> outer,
1380 Handle<ScopeInfo> scope_info) {
1381 DCHECK_EQ(scope_info->scope_type(), MODULE_SCOPE);
1382 Handle<Context> context = NewFixedArrayWithMap<Context>(
1383 Heap::kModuleContextMapRootIndex, scope_info->ContextLength(), TENURED);
1384 context->set_scope_info(*scope_info);
1385 context->set_previous(*outer);
1386 context->set_extension(*module);
1387 context->set_native_context(*outer);
1388 DCHECK(context->IsModuleContext());
1389 return context;
1390 }
1391
NewFunctionContext(Handle<Context> outer,Handle<ScopeInfo> scope_info)1392 Handle<Context> Factory::NewFunctionContext(Handle<Context> outer,
1393 Handle<ScopeInfo> scope_info) {
1394 int length = scope_info->ContextLength();
1395 DCHECK_LE(Context::MIN_CONTEXT_SLOTS, length);
1396 Heap::RootListIndex mapRootIndex;
1397 switch (scope_info->scope_type()) {
1398 case EVAL_SCOPE:
1399 mapRootIndex = Heap::kEvalContextMapRootIndex;
1400 break;
1401 case FUNCTION_SCOPE:
1402 mapRootIndex = Heap::kFunctionContextMapRootIndex;
1403 break;
1404 default:
1405 UNREACHABLE();
1406 }
1407 Handle<Context> context = NewFixedArrayWithMap<Context>(mapRootIndex, length);
1408 context->set_scope_info(*scope_info);
1409 context->set_previous(*outer);
1410 context->set_extension(*the_hole_value());
1411 context->set_native_context(outer->native_context());
1412 return context;
1413 }
1414
NewCatchContext(Handle<Context> previous,Handle<ScopeInfo> scope_info,Handle<Object> thrown_object)1415 Handle<Context> Factory::NewCatchContext(Handle<Context> previous,
1416 Handle<ScopeInfo> scope_info,
1417 Handle<Object> thrown_object) {
1418 STATIC_ASSERT(Context::MIN_CONTEXT_SLOTS == Context::THROWN_OBJECT_INDEX);
1419 Handle<Context> context = NewFixedArrayWithMap<Context>(
1420 Heap::kCatchContextMapRootIndex, Context::MIN_CONTEXT_SLOTS + 1);
1421 context->set_scope_info(*scope_info);
1422 context->set_previous(*previous);
1423 context->set_extension(*the_hole_value());
1424 context->set_native_context(previous->native_context());
1425 context->set(Context::THROWN_OBJECT_INDEX, *thrown_object);
1426 return context;
1427 }
1428
NewDebugEvaluateContext(Handle<Context> previous,Handle<ScopeInfo> scope_info,Handle<JSReceiver> extension,Handle<Context> wrapped,Handle<StringSet> whitelist)1429 Handle<Context> Factory::NewDebugEvaluateContext(Handle<Context> previous,
1430 Handle<ScopeInfo> scope_info,
1431 Handle<JSReceiver> extension,
1432 Handle<Context> wrapped,
1433 Handle<StringSet> whitelist) {
1434 STATIC_ASSERT(Context::WHITE_LIST_INDEX == Context::MIN_CONTEXT_SLOTS + 1);
1435 DCHECK(scope_info->IsDebugEvaluateScope());
1436 Handle<HeapObject> ext = extension.is_null()
1437 ? Handle<HeapObject>::cast(the_hole_value())
1438 : Handle<HeapObject>::cast(extension);
1439 Handle<Context> c = NewFixedArrayWithMap<Context>(
1440 Heap::kDebugEvaluateContextMapRootIndex, Context::MIN_CONTEXT_SLOTS + 2);
1441 c->set_scope_info(*scope_info);
1442 c->set_previous(*previous);
1443 c->set_native_context(previous->native_context());
1444 c->set_extension(*ext);
1445 if (!wrapped.is_null()) c->set(Context::WRAPPED_CONTEXT_INDEX, *wrapped);
1446 if (!whitelist.is_null()) c->set(Context::WHITE_LIST_INDEX, *whitelist);
1447 return c;
1448 }
1449
NewWithContext(Handle<Context> previous,Handle<ScopeInfo> scope_info,Handle<JSReceiver> extension)1450 Handle<Context> Factory::NewWithContext(Handle<Context> previous,
1451 Handle<ScopeInfo> scope_info,
1452 Handle<JSReceiver> extension) {
1453 Handle<Context> context = NewFixedArrayWithMap<Context>(
1454 Heap::kWithContextMapRootIndex, Context::MIN_CONTEXT_SLOTS);
1455 context->set_scope_info(*scope_info);
1456 context->set_previous(*previous);
1457 context->set_extension(*extension);
1458 context->set_native_context(previous->native_context());
1459 return context;
1460 }
1461
NewBlockContext(Handle<Context> previous,Handle<ScopeInfo> scope_info)1462 Handle<Context> Factory::NewBlockContext(Handle<Context> previous,
1463 Handle<ScopeInfo> scope_info) {
1464 DCHECK_EQ(scope_info->scope_type(), BLOCK_SCOPE);
1465 Handle<Context> context = NewFixedArrayWithMap<Context>(
1466 Heap::kBlockContextMapRootIndex, scope_info->ContextLength());
1467 context->set_scope_info(*scope_info);
1468 context->set_previous(*previous);
1469 context->set_extension(*the_hole_value());
1470 context->set_native_context(previous->native_context());
1471 return context;
1472 }
1473
NewStruct(InstanceType type,PretenureFlag pretenure)1474 Handle<Struct> Factory::NewStruct(InstanceType type, PretenureFlag pretenure) {
1475 Map* map;
1476 switch (type) {
1477 #define MAKE_CASE(NAME, Name, name) \
1478 case NAME##_TYPE: \
1479 map = *name##_map(); \
1480 break;
1481 STRUCT_LIST(MAKE_CASE)
1482 #undef MAKE_CASE
1483 default:
1484 UNREACHABLE();
1485 }
1486 int size = map->instance_size();
1487 HeapObject* result = AllocateRawWithImmortalMap(size, pretenure, map);
1488 Handle<Struct> str(Struct::cast(result), isolate());
1489 str->InitializeBody(size);
1490 return str;
1491 }
1492
NewAliasedArgumentsEntry(int aliased_context_slot)1493 Handle<AliasedArgumentsEntry> Factory::NewAliasedArgumentsEntry(
1494 int aliased_context_slot) {
1495 Handle<AliasedArgumentsEntry> entry = Handle<AliasedArgumentsEntry>::cast(
1496 NewStruct(ALIASED_ARGUMENTS_ENTRY_TYPE, NOT_TENURED));
1497 entry->set_aliased_context_slot(aliased_context_slot);
1498 return entry;
1499 }
1500
NewAccessorInfo()1501 Handle<AccessorInfo> Factory::NewAccessorInfo() {
1502 Handle<AccessorInfo> info =
1503 Handle<AccessorInfo>::cast(NewStruct(ACCESSOR_INFO_TYPE, TENURED));
1504 info->set_name(*empty_string());
1505 info->set_flags(0); // Must clear the flags, it was initialized as undefined.
1506 info->set_is_sloppy(true);
1507 info->set_initial_property_attributes(NONE);
1508 return info;
1509 }
1510
NewScript(Handle<String> source,PretenureFlag tenure)1511 Handle<Script> Factory::NewScript(Handle<String> source, PretenureFlag tenure) {
1512 DCHECK(tenure == TENURED || tenure == TENURED_READ_ONLY);
1513 // Create and initialize script object.
1514 Heap* heap = isolate()->heap();
1515 Handle<Script> script = Handle<Script>::cast(NewStruct(SCRIPT_TYPE, tenure));
1516 script->set_source(*source);
1517 script->set_name(heap->undefined_value());
1518 script->set_id(isolate()->heap()->NextScriptId());
1519 script->set_line_offset(0);
1520 script->set_column_offset(0);
1521 script->set_context_data(heap->undefined_value());
1522 script->set_type(Script::TYPE_NORMAL);
1523 script->set_wrapper(heap->undefined_value());
1524 script->set_line_ends(heap->undefined_value());
1525 script->set_eval_from_shared_or_wrapped_arguments(heap->undefined_value());
1526 script->set_eval_from_position(0);
1527 script->set_shared_function_infos(*empty_weak_fixed_array(),
1528 SKIP_WRITE_BARRIER);
1529 script->set_flags(0);
1530 script->set_host_defined_options(*empty_fixed_array());
1531 heap->set_script_list(*FixedArrayOfWeakCells::Add(script_list(), script));
1532 return script;
1533 }
1534
NewCallableTask(Handle<JSReceiver> callable,Handle<Context> context)1535 Handle<CallableTask> Factory::NewCallableTask(Handle<JSReceiver> callable,
1536 Handle<Context> context) {
1537 DCHECK(callable->IsCallable());
1538 Handle<CallableTask> microtask =
1539 Handle<CallableTask>::cast(NewStruct(CALLABLE_TASK_TYPE));
1540 microtask->set_callable(*callable);
1541 microtask->set_context(*context);
1542 return microtask;
1543 }
1544
NewCallbackTask(Handle<Foreign> callback,Handle<Foreign> data)1545 Handle<CallbackTask> Factory::NewCallbackTask(Handle<Foreign> callback,
1546 Handle<Foreign> data) {
1547 Handle<CallbackTask> microtask =
1548 Handle<CallbackTask>::cast(NewStruct(CALLBACK_TASK_TYPE));
1549 microtask->set_callback(*callback);
1550 microtask->set_data(*data);
1551 return microtask;
1552 }
1553
NewPromiseResolveThenableJobTask(Handle<JSPromise> promise_to_resolve,Handle<JSReceiver> then,Handle<JSReceiver> thenable,Handle<Context> context)1554 Handle<PromiseResolveThenableJobTask> Factory::NewPromiseResolveThenableJobTask(
1555 Handle<JSPromise> promise_to_resolve, Handle<JSReceiver> then,
1556 Handle<JSReceiver> thenable, Handle<Context> context) {
1557 DCHECK(then->IsCallable());
1558 Handle<PromiseResolveThenableJobTask> microtask =
1559 Handle<PromiseResolveThenableJobTask>::cast(
1560 NewStruct(PROMISE_RESOLVE_THENABLE_JOB_TASK_TYPE));
1561 microtask->set_promise_to_resolve(*promise_to_resolve);
1562 microtask->set_then(*then);
1563 microtask->set_thenable(*thenable);
1564 microtask->set_context(*context);
1565 return microtask;
1566 }
1567
NewForeign(Address addr,PretenureFlag pretenure)1568 Handle<Foreign> Factory::NewForeign(Address addr, PretenureFlag pretenure) {
1569 // Statically ensure that it is safe to allocate foreigns in paged spaces.
1570 STATIC_ASSERT(Foreign::kSize <= kMaxRegularHeapObjectSize);
1571 Map* map = *foreign_map();
1572 HeapObject* result =
1573 AllocateRawWithImmortalMap(map->instance_size(), pretenure, map);
1574 Handle<Foreign> foreign(Foreign::cast(result), isolate());
1575 foreign->set_foreign_address(addr);
1576 return foreign;
1577 }
1578
NewByteArray(int length,PretenureFlag pretenure)1579 Handle<ByteArray> Factory::NewByteArray(int length, PretenureFlag pretenure) {
1580 DCHECK_LE(0, length);
1581 if (length > ByteArray::kMaxLength) {
1582 isolate()->heap()->FatalProcessOutOfMemory("invalid array length");
1583 }
1584 int size = ByteArray::SizeFor(length);
1585 HeapObject* result =
1586 AllocateRawWithImmortalMap(size, pretenure, *byte_array_map());
1587 Handle<ByteArray> array(ByteArray::cast(result), isolate());
1588 array->set_length(length);
1589 array->clear_padding();
1590 return array;
1591 }
1592
NewBytecodeArray(int length,const byte * raw_bytecodes,int frame_size,int parameter_count,Handle<FixedArray> constant_pool)1593 Handle<BytecodeArray> Factory::NewBytecodeArray(
1594 int length, const byte* raw_bytecodes, int frame_size, int parameter_count,
1595 Handle<FixedArray> constant_pool) {
1596 DCHECK_LE(0, length);
1597 if (length > BytecodeArray::kMaxLength) {
1598 isolate()->heap()->FatalProcessOutOfMemory("invalid array length");
1599 }
1600 // Bytecode array is pretenured, so constant pool array should be too.
1601 DCHECK(!isolate()->heap()->InNewSpace(*constant_pool));
1602
1603 int size = BytecodeArray::SizeFor(length);
1604 HeapObject* result =
1605 AllocateRawWithImmortalMap(size, TENURED, *bytecode_array_map());
1606 Handle<BytecodeArray> instance(BytecodeArray::cast(result), isolate());
1607 instance->set_length(length);
1608 instance->set_frame_size(frame_size);
1609 instance->set_parameter_count(parameter_count);
1610 instance->set_incoming_new_target_or_generator_register(
1611 interpreter::Register::invalid_value());
1612 instance->set_interrupt_budget(interpreter::Interpreter::InterruptBudget());
1613 instance->set_osr_loop_nesting_level(0);
1614 instance->set_bytecode_age(BytecodeArray::kNoAgeBytecodeAge);
1615 instance->set_constant_pool(*constant_pool);
1616 instance->set_handler_table(*empty_byte_array());
1617 instance->set_source_position_table(*empty_byte_array());
1618 CopyBytes(reinterpret_cast<byte*>(instance->GetFirstBytecodeAddress()),
1619 raw_bytecodes, length);
1620 instance->clear_padding();
1621
1622 return instance;
1623 }
1624
NewFixedTypedArrayWithExternalPointer(int length,ExternalArrayType array_type,void * external_pointer,PretenureFlag pretenure)1625 Handle<FixedTypedArrayBase> Factory::NewFixedTypedArrayWithExternalPointer(
1626 int length, ExternalArrayType array_type, void* external_pointer,
1627 PretenureFlag pretenure) {
1628 DCHECK(0 <= length && length <= Smi::kMaxValue);
1629 int size = FixedTypedArrayBase::kHeaderSize;
1630 HeapObject* result = AllocateRawWithImmortalMap(
1631 size, pretenure, isolate()->heap()->MapForFixedTypedArray(array_type));
1632 Handle<FixedTypedArrayBase> elements(FixedTypedArrayBase::cast(result),
1633 isolate());
1634 elements->set_base_pointer(Smi::kZero, SKIP_WRITE_BARRIER);
1635 elements->set_external_pointer(external_pointer, SKIP_WRITE_BARRIER);
1636 elements->set_length(length);
1637 return elements;
1638 }
1639
NewFixedTypedArray(size_t length,size_t byte_length,ExternalArrayType array_type,bool initialize,PretenureFlag pretenure)1640 Handle<FixedTypedArrayBase> Factory::NewFixedTypedArray(
1641 size_t length, size_t byte_length, ExternalArrayType array_type,
1642 bool initialize, PretenureFlag pretenure) {
1643 DCHECK(0 <= length && length <= Smi::kMaxValue);
1644 CHECK(byte_length <= kMaxInt - FixedTypedArrayBase::kDataOffset);
1645 size_t size =
1646 OBJECT_POINTER_ALIGN(byte_length + FixedTypedArrayBase::kDataOffset);
1647 Map* map = isolate()->heap()->MapForFixedTypedArray(array_type);
1648 AllocationAlignment alignment =
1649 array_type == kExternalFloat64Array ? kDoubleAligned : kWordAligned;
1650 HeapObject* object = AllocateRawWithImmortalMap(static_cast<int>(size),
1651 pretenure, map, alignment);
1652
1653 Handle<FixedTypedArrayBase> elements(FixedTypedArrayBase::cast(object),
1654 isolate());
1655 elements->set_base_pointer(*elements, SKIP_WRITE_BARRIER);
1656 elements->set_external_pointer(
1657 reinterpret_cast<void*>(
1658 ExternalReference::fixed_typed_array_base_data_offset().address()),
1659 SKIP_WRITE_BARRIER);
1660 elements->set_length(static_cast<int>(length));
1661 if (initialize) memset(elements->DataPtr(), 0, elements->DataSize());
1662 return elements;
1663 }
1664
NewCell(Handle<Object> value)1665 Handle<Cell> Factory::NewCell(Handle<Object> value) {
1666 AllowDeferredHandleDereference convert_to_cell;
1667 STATIC_ASSERT(Cell::kSize <= kMaxRegularHeapObjectSize);
1668 HeapObject* result =
1669 AllocateRawWithImmortalMap(Cell::kSize, TENURED, *cell_map());
1670 Handle<Cell> cell(Cell::cast(result), isolate());
1671 cell->set_value(*value);
1672 return cell;
1673 }
1674
NewNoClosuresCell(Handle<HeapObject> value)1675 Handle<FeedbackCell> Factory::NewNoClosuresCell(Handle<HeapObject> value) {
1676 AllowDeferredHandleDereference convert_to_cell;
1677 HeapObject* result = AllocateRawWithImmortalMap(FeedbackCell::kSize, TENURED,
1678 *no_closures_cell_map());
1679 Handle<FeedbackCell> cell(FeedbackCell::cast(result), isolate());
1680 cell->set_value(*value);
1681 return cell;
1682 }
1683
NewOneClosureCell(Handle<HeapObject> value)1684 Handle<FeedbackCell> Factory::NewOneClosureCell(Handle<HeapObject> value) {
1685 AllowDeferredHandleDereference convert_to_cell;
1686 HeapObject* result = AllocateRawWithImmortalMap(FeedbackCell::kSize, TENURED,
1687 *one_closure_cell_map());
1688 Handle<FeedbackCell> cell(FeedbackCell::cast(result), isolate());
1689 cell->set_value(*value);
1690 return cell;
1691 }
1692
NewManyClosuresCell(Handle<HeapObject> value)1693 Handle<FeedbackCell> Factory::NewManyClosuresCell(Handle<HeapObject> value) {
1694 AllowDeferredHandleDereference convert_to_cell;
1695 HeapObject* result = AllocateRawWithImmortalMap(FeedbackCell::kSize, TENURED,
1696 *many_closures_cell_map());
1697 Handle<FeedbackCell> cell(FeedbackCell::cast(result), isolate());
1698 cell->set_value(*value);
1699 return cell;
1700 }
1701
NewPropertyCell(Handle<Name> name,PretenureFlag pretenure)1702 Handle<PropertyCell> Factory::NewPropertyCell(Handle<Name> name,
1703 PretenureFlag pretenure) {
1704 DCHECK(name->IsUniqueName());
1705 STATIC_ASSERT(PropertyCell::kSize <= kMaxRegularHeapObjectSize);
1706 HeapObject* result = AllocateRawWithImmortalMap(
1707 PropertyCell::kSize, pretenure, *global_property_cell_map());
1708 Handle<PropertyCell> cell(PropertyCell::cast(result), isolate());
1709 cell->set_dependent_code(DependentCode::cast(*empty_fixed_array()),
1710 SKIP_WRITE_BARRIER);
1711 cell->set_property_details(PropertyDetails(Smi::kZero));
1712 cell->set_name(*name);
1713 cell->set_value(*the_hole_value());
1714 return cell;
1715 }
1716
NewWeakCell(Handle<HeapObject> value,PretenureFlag pretenure)1717 Handle<WeakCell> Factory::NewWeakCell(Handle<HeapObject> value,
1718 PretenureFlag pretenure) {
1719 // It is safe to dereference the value because we are embedding it
1720 // in cell and not inspecting its fields.
1721 AllowDeferredHandleDereference convert_to_cell;
1722 STATIC_ASSERT(WeakCell::kSize <= kMaxRegularHeapObjectSize);
1723 HeapObject* result =
1724 AllocateRawWithImmortalMap(WeakCell::kSize, pretenure, *weak_cell_map());
1725 Handle<WeakCell> cell(WeakCell::cast(result), isolate());
1726 cell->initialize(*value);
1727 return cell;
1728 }
1729
NewTransitionArray(int number_of_transitions,int slack)1730 Handle<TransitionArray> Factory::NewTransitionArray(int number_of_transitions,
1731 int slack) {
1732 int capacity = TransitionArray::LengthFor(number_of_transitions + slack);
1733 Handle<TransitionArray> array = NewWeakFixedArrayWithMap<TransitionArray>(
1734 Heap::kTransitionArrayMapRootIndex, capacity, TENURED);
1735 // Transition arrays are tenured. When black allocation is on we have to
1736 // add the transition array to the list of encountered_transition_arrays.
1737 Heap* heap = isolate()->heap();
1738 if (heap->incremental_marking()->black_allocation()) {
1739 heap->mark_compact_collector()->AddTransitionArray(*array);
1740 }
1741 array->WeakFixedArray::Set(TransitionArray::kPrototypeTransitionsIndex,
1742 MaybeObject::FromObject(Smi::kZero));
1743 array->WeakFixedArray::Set(
1744 TransitionArray::kTransitionLengthIndex,
1745 MaybeObject::FromObject(Smi::FromInt(number_of_transitions)));
1746 return array;
1747 }
1748
NewAllocationSite()1749 Handle<AllocationSite> Factory::NewAllocationSite() {
1750 Handle<Map> map = allocation_site_map();
1751 Handle<AllocationSite> site(AllocationSite::cast(New(map, TENURED)),
1752 isolate());
1753 site->Initialize();
1754
1755 // Link the site
1756 site->set_weak_next(isolate()->heap()->allocation_sites_list());
1757 isolate()->heap()->set_allocation_sites_list(*site);
1758 return site;
1759 }
1760
NewMap(InstanceType type,int instance_size,ElementsKind elements_kind,int inobject_properties)1761 Handle<Map> Factory::NewMap(InstanceType type, int instance_size,
1762 ElementsKind elements_kind,
1763 int inobject_properties) {
1764 STATIC_ASSERT(LAST_JS_OBJECT_TYPE == LAST_TYPE);
1765 DCHECK_IMPLIES(Map::IsJSObject(type) &&
1766 !Map::CanHaveFastTransitionableElementsKind(type),
1767 IsDictionaryElementsKind(elements_kind) ||
1768 IsTerminalElementsKind(elements_kind));
1769 HeapObject* result =
1770 isolate()->heap()->AllocateRawWithRetryOrFail(Map::kSize, MAP_SPACE);
1771 result->set_map_after_allocation(*meta_map(), SKIP_WRITE_BARRIER);
1772 return handle(InitializeMap(Map::cast(result), type, instance_size,
1773 elements_kind, inobject_properties),
1774 isolate());
1775 }
1776
InitializeMap(Map * map,InstanceType type,int instance_size,ElementsKind elements_kind,int inobject_properties)1777 Map* Factory::InitializeMap(Map* map, InstanceType type, int instance_size,
1778 ElementsKind elements_kind,
1779 int inobject_properties) {
1780 map->set_instance_type(type);
1781 map->set_prototype(*null_value(), SKIP_WRITE_BARRIER);
1782 map->set_constructor_or_backpointer(*null_value(), SKIP_WRITE_BARRIER);
1783 map->set_instance_size(instance_size);
1784 if (map->IsJSObjectMap()) {
1785 DCHECK(!isolate()->heap()->InReadOnlySpace(map));
1786 map->SetInObjectPropertiesStartInWords(instance_size / kPointerSize -
1787 inobject_properties);
1788 DCHECK_EQ(map->GetInObjectProperties(), inobject_properties);
1789 map->set_prototype_validity_cell(*invalid_prototype_validity_cell());
1790 } else {
1791 DCHECK_EQ(inobject_properties, 0);
1792 map->set_inobject_properties_start_or_constructor_function_index(0);
1793 map->set_prototype_validity_cell(Smi::FromInt(Map::kPrototypeChainValid));
1794 }
1795 map->set_dependent_code(DependentCode::cast(*empty_fixed_array()),
1796 SKIP_WRITE_BARRIER);
1797 map->set_weak_cell_cache(Smi::kZero);
1798 map->set_raw_transitions(MaybeObject::FromSmi(Smi::kZero));
1799 map->SetInObjectUnusedPropertyFields(inobject_properties);
1800 map->set_instance_descriptors(*empty_descriptor_array());
1801 if (FLAG_unbox_double_fields) {
1802 map->set_layout_descriptor(LayoutDescriptor::FastPointerLayout());
1803 }
1804 // Must be called only after |instance_type|, |instance_size| and
1805 // |layout_descriptor| are set.
1806 map->set_visitor_id(Map::GetVisitorId(map));
1807 map->set_bit_field(0);
1808 map->set_bit_field2(Map::IsExtensibleBit::kMask);
1809 DCHECK(!map->is_in_retained_map_list());
1810 int bit_field3 = Map::EnumLengthBits::encode(kInvalidEnumCacheSentinel) |
1811 Map::OwnsDescriptorsBit::encode(true) |
1812 Map::ConstructionCounterBits::encode(Map::kNoSlackTracking);
1813 map->set_bit_field3(bit_field3);
1814 map->set_elements_kind(elements_kind);
1815 map->set_new_target_is_base(true);
1816 isolate()->counters()->maps_created()->Increment();
1817 if (FLAG_trace_maps) LOG(isolate(), MapCreate(map));
1818 return map;
1819 }
1820
CopyJSObject(Handle<JSObject> source)1821 Handle<JSObject> Factory::CopyJSObject(Handle<JSObject> source) {
1822 return CopyJSObjectWithAllocationSite(source, Handle<AllocationSite>());
1823 }
1824
CopyJSObjectWithAllocationSite(Handle<JSObject> source,Handle<AllocationSite> site)1825 Handle<JSObject> Factory::CopyJSObjectWithAllocationSite(
1826 Handle<JSObject> source, Handle<AllocationSite> site) {
1827 Handle<Map> map(source->map(), isolate());
1828
1829 // We can only clone regexps, normal objects, api objects, errors or arrays.
1830 // Copying anything else will break invariants.
1831 CHECK(map->instance_type() == JS_REGEXP_TYPE ||
1832 map->instance_type() == JS_OBJECT_TYPE ||
1833 map->instance_type() == JS_ERROR_TYPE ||
1834 map->instance_type() == JS_ARRAY_TYPE ||
1835 map->instance_type() == JS_API_OBJECT_TYPE ||
1836 map->instance_type() == WASM_GLOBAL_TYPE ||
1837 map->instance_type() == WASM_INSTANCE_TYPE ||
1838 map->instance_type() == WASM_MEMORY_TYPE ||
1839 map->instance_type() == WASM_MODULE_TYPE ||
1840 map->instance_type() == WASM_TABLE_TYPE ||
1841 map->instance_type() == JS_SPECIAL_API_OBJECT_TYPE);
1842 DCHECK(site.is_null() || AllocationSite::CanTrack(map->instance_type()));
1843
1844 int object_size = map->instance_size();
1845 int adjusted_object_size =
1846 site.is_null() ? object_size : object_size + AllocationMemento::kSize;
1847 HeapObject* raw_clone = isolate()->heap()->AllocateRawWithRetryOrFail(
1848 adjusted_object_size, NEW_SPACE);
1849
1850 SLOW_DCHECK(isolate()->heap()->InNewSpace(raw_clone));
1851 // Since we know the clone is allocated in new space, we can copy
1852 // the contents without worrying about updating the write barrier.
1853 Heap::CopyBlock(raw_clone->address(), source->address(), object_size);
1854 Handle<JSObject> clone(JSObject::cast(raw_clone), isolate());
1855
1856 if (!site.is_null()) {
1857 AllocationMemento* alloc_memento = reinterpret_cast<AllocationMemento*>(
1858 reinterpret_cast<Address>(raw_clone) + object_size);
1859 InitializeAllocationMemento(alloc_memento, *site);
1860 }
1861
1862 SLOW_DCHECK(clone->GetElementsKind() == source->GetElementsKind());
1863 FixedArrayBase* elements = FixedArrayBase::cast(source->elements());
1864 // Update elements if necessary.
1865 if (elements->length() > 0) {
1866 FixedArrayBase* elem = nullptr;
1867 if (elements->map() == *fixed_cow_array_map()) {
1868 elem = elements;
1869 } else if (source->HasDoubleElements()) {
1870 elem = *CopyFixedDoubleArray(
1871 handle(FixedDoubleArray::cast(elements), isolate()));
1872 } else {
1873 elem = *CopyFixedArray(handle(FixedArray::cast(elements), isolate()));
1874 }
1875 clone->set_elements(elem);
1876 }
1877
1878 // Update properties if necessary.
1879 if (source->HasFastProperties()) {
1880 PropertyArray* properties = source->property_array();
1881 if (properties->length() > 0) {
1882 // TODO(gsathya): Do not copy hash code.
1883 Handle<PropertyArray> prop = CopyArrayWithMap(
1884 handle(properties, isolate()), handle(properties->map(), isolate()));
1885 clone->set_raw_properties_or_hash(*prop);
1886 }
1887 } else {
1888 Handle<FixedArray> properties(
1889 FixedArray::cast(source->property_dictionary()), isolate());
1890 Handle<FixedArray> prop = CopyFixedArray(properties);
1891 clone->set_raw_properties_or_hash(*prop);
1892 }
1893 return clone;
1894 }
1895
1896 namespace {
1897 template <typename T>
initialize_length(T * array,int length)1898 void initialize_length(T* array, int length) {
1899 array->set_length(length);
1900 }
1901
1902 template <>
initialize_length(PropertyArray * array,int length)1903 void initialize_length<PropertyArray>(PropertyArray* array, int length) {
1904 array->initialize_length(length);
1905 }
1906
1907 } // namespace
1908
1909 template <typename T>
CopyArrayWithMap(Handle<T> src,Handle<Map> map)1910 Handle<T> Factory::CopyArrayWithMap(Handle<T> src, Handle<Map> map) {
1911 int len = src->length();
1912 HeapObject* obj = AllocateRawFixedArray(len, NOT_TENURED);
1913 obj->set_map_after_allocation(*map, SKIP_WRITE_BARRIER);
1914
1915 T* result = T::cast(obj);
1916 DisallowHeapAllocation no_gc;
1917 WriteBarrierMode mode = result->GetWriteBarrierMode(no_gc);
1918
1919 if (mode == SKIP_WRITE_BARRIER) {
1920 // Eliminate the write barrier if possible.
1921 Heap::CopyBlock(obj->address() + kPointerSize,
1922 src->address() + kPointerSize,
1923 T::SizeFor(len) - kPointerSize);
1924 } else {
1925 // Slow case: Just copy the content one-by-one.
1926 initialize_length(result, len);
1927 for (int i = 0; i < len; i++) result->set(i, src->get(i), mode);
1928 }
1929 return Handle<T>(result, isolate());
1930 }
1931
1932 template <typename T>
CopyArrayAndGrow(Handle<T> src,int grow_by,PretenureFlag pretenure)1933 Handle<T> Factory::CopyArrayAndGrow(Handle<T> src, int grow_by,
1934 PretenureFlag pretenure) {
1935 DCHECK_LT(0, grow_by);
1936 DCHECK_LE(grow_by, kMaxInt - src->length());
1937 int old_len = src->length();
1938 int new_len = old_len + grow_by;
1939 HeapObject* obj = AllocateRawFixedArray(new_len, pretenure);
1940 obj->set_map_after_allocation(src->map(), SKIP_WRITE_BARRIER);
1941
1942 T* result = T::cast(obj);
1943 initialize_length(result, new_len);
1944
1945 // Copy the content.
1946 DisallowHeapAllocation no_gc;
1947 WriteBarrierMode mode = obj->GetWriteBarrierMode(no_gc);
1948 for (int i = 0; i < old_len; i++) result->set(i, src->get(i), mode);
1949 MemsetPointer(result->data_start() + old_len, *undefined_value(), grow_by);
1950 return Handle<T>(result, isolate());
1951 }
1952
CopyFixedArrayWithMap(Handle<FixedArray> array,Handle<Map> map)1953 Handle<FixedArray> Factory::CopyFixedArrayWithMap(Handle<FixedArray> array,
1954 Handle<Map> map) {
1955 return CopyArrayWithMap(array, map);
1956 }
1957
CopyFixedArrayAndGrow(Handle<FixedArray> array,int grow_by,PretenureFlag pretenure)1958 Handle<FixedArray> Factory::CopyFixedArrayAndGrow(Handle<FixedArray> array,
1959 int grow_by,
1960 PretenureFlag pretenure) {
1961 return CopyArrayAndGrow(array, grow_by, pretenure);
1962 }
1963
CopyWeakFixedArrayAndGrow(Handle<WeakFixedArray> src,int grow_by,PretenureFlag pretenure)1964 Handle<WeakFixedArray> Factory::CopyWeakFixedArrayAndGrow(
1965 Handle<WeakFixedArray> src, int grow_by, PretenureFlag pretenure) {
1966 DCHECK(
1967 !src->IsTransitionArray()); // Compacted by GC, this code doesn't work.
1968 int old_len = src->length();
1969 int new_len = old_len + grow_by;
1970 DCHECK_GE(new_len, old_len);
1971 HeapObject* obj = AllocateRawFixedArray(new_len, pretenure);
1972 DCHECK_EQ(old_len, src->length());
1973 obj->set_map_after_allocation(src->map(), SKIP_WRITE_BARRIER);
1974
1975 WeakFixedArray* result = WeakFixedArray::cast(obj);
1976 result->set_length(new_len);
1977
1978 // Copy the content.
1979 DisallowHeapAllocation no_gc;
1980 WriteBarrierMode mode = obj->GetWriteBarrierMode(no_gc);
1981 for (int i = 0; i < old_len; i++) result->Set(i, src->Get(i), mode);
1982 HeapObjectReference* undefined_reference =
1983 HeapObjectReference::Strong(isolate()->heap()->undefined_value());
1984 MemsetPointer(result->data_start() + old_len, undefined_reference, grow_by);
1985 return Handle<WeakFixedArray>(result, isolate());
1986 }
1987
CopyWeakArrayListAndGrow(Handle<WeakArrayList> src,int grow_by,PretenureFlag pretenure)1988 Handle<WeakArrayList> Factory::CopyWeakArrayListAndGrow(
1989 Handle<WeakArrayList> src, int grow_by, PretenureFlag pretenure) {
1990 int old_capacity = src->capacity();
1991 int new_capacity = old_capacity + grow_by;
1992 DCHECK_GE(new_capacity, old_capacity);
1993 HeapObject* obj = AllocateRawWeakArrayList(new_capacity, pretenure);
1994 obj->set_map_after_allocation(src->map(), SKIP_WRITE_BARRIER);
1995
1996 WeakArrayList* result = WeakArrayList::cast(obj);
1997 result->set_length(src->length());
1998 result->set_capacity(new_capacity);
1999
2000 // Copy the content.
2001 DisallowHeapAllocation no_gc;
2002 WriteBarrierMode mode = obj->GetWriteBarrierMode(no_gc);
2003 for (int i = 0; i < old_capacity; i++) result->Set(i, src->Get(i), mode);
2004 HeapObjectReference* undefined_reference =
2005 HeapObjectReference::Strong(isolate()->heap()->undefined_value());
2006 MemsetPointer(result->data_start() + old_capacity, undefined_reference,
2007 grow_by);
2008 return Handle<WeakArrayList>(result, isolate());
2009 }
2010
CopyPropertyArrayAndGrow(Handle<PropertyArray> array,int grow_by,PretenureFlag pretenure)2011 Handle<PropertyArray> Factory::CopyPropertyArrayAndGrow(
2012 Handle<PropertyArray> array, int grow_by, PretenureFlag pretenure) {
2013 return CopyArrayAndGrow(array, grow_by, pretenure);
2014 }
2015
CopyFixedArrayUpTo(Handle<FixedArray> array,int new_len,PretenureFlag pretenure)2016 Handle<FixedArray> Factory::CopyFixedArrayUpTo(Handle<FixedArray> array,
2017 int new_len,
2018 PretenureFlag pretenure) {
2019 DCHECK_LE(0, new_len);
2020 DCHECK_LE(new_len, array->length());
2021 if (new_len == 0) return empty_fixed_array();
2022
2023 HeapObject* obj = AllocateRawFixedArray(new_len, pretenure);
2024 obj->set_map_after_allocation(*fixed_array_map(), SKIP_WRITE_BARRIER);
2025 Handle<FixedArray> result(FixedArray::cast(obj), isolate());
2026 result->set_length(new_len);
2027
2028 // Copy the content.
2029 DisallowHeapAllocation no_gc;
2030 WriteBarrierMode mode = result->GetWriteBarrierMode(no_gc);
2031 for (int i = 0; i < new_len; i++) result->set(i, array->get(i), mode);
2032 return result;
2033 }
2034
CopyFixedArray(Handle<FixedArray> array)2035 Handle<FixedArray> Factory::CopyFixedArray(Handle<FixedArray> array) {
2036 if (array->length() == 0) return array;
2037 return CopyArrayWithMap(array, handle(array->map(), isolate()));
2038 }
2039
CopyAndTenureFixedCOWArray(Handle<FixedArray> array)2040 Handle<FixedArray> Factory::CopyAndTenureFixedCOWArray(
2041 Handle<FixedArray> array) {
2042 DCHECK(isolate()->heap()->InNewSpace(*array));
2043 Handle<FixedArray> result =
2044 CopyFixedArrayUpTo(array, array->length(), TENURED);
2045
2046 // TODO(mvstanton): The map is set twice because of protection against calling
2047 // set() on a COW FixedArray. Issue v8:3221 created to track this, and
2048 // we might then be able to remove this whole method.
2049 result->set_map_after_allocation(*fixed_cow_array_map(), SKIP_WRITE_BARRIER);
2050 return result;
2051 }
2052
CopyFixedDoubleArray(Handle<FixedDoubleArray> array)2053 Handle<FixedDoubleArray> Factory::CopyFixedDoubleArray(
2054 Handle<FixedDoubleArray> array) {
2055 int len = array->length();
2056 if (len == 0) return array;
2057 Handle<FixedDoubleArray> result =
2058 Handle<FixedDoubleArray>::cast(NewFixedDoubleArray(len, NOT_TENURED));
2059 Heap::CopyBlock(
2060 result->address() + FixedDoubleArray::kLengthOffset,
2061 array->address() + FixedDoubleArray::kLengthOffset,
2062 FixedDoubleArray::SizeFor(len) - FixedDoubleArray::kLengthOffset);
2063 return result;
2064 }
2065
CopyFeedbackVector(Handle<FeedbackVector> array)2066 Handle<FeedbackVector> Factory::CopyFeedbackVector(
2067 Handle<FeedbackVector> array) {
2068 int len = array->length();
2069 HeapObject* obj = AllocateRawWithImmortalMap(
2070 FeedbackVector::SizeFor(len), NOT_TENURED, *feedback_vector_map());
2071 Handle<FeedbackVector> result(FeedbackVector::cast(obj), isolate());
2072
2073 DisallowHeapAllocation no_gc;
2074 WriteBarrierMode mode = result->GetWriteBarrierMode(no_gc);
2075
2076 // Eliminate the write barrier if possible.
2077 if (mode == SKIP_WRITE_BARRIER) {
2078 Heap::CopyBlock(result->address() + kPointerSize,
2079 result->address() + kPointerSize,
2080 FeedbackVector::SizeFor(len) - kPointerSize);
2081 } else {
2082 // Slow case: Just copy the content one-by-one.
2083 result->set_shared_function_info(array->shared_function_info());
2084 result->set_optimized_code_weak_or_smi(array->optimized_code_weak_or_smi());
2085 result->set_invocation_count(array->invocation_count());
2086 result->set_profiler_ticks(array->profiler_ticks());
2087 result->set_deopt_count(array->deopt_count());
2088 for (int i = 0; i < len; i++) result->set(i, array->get(i), mode);
2089 }
2090 return result;
2091 }
2092
NewNumber(double value,PretenureFlag pretenure)2093 Handle<Object> Factory::NewNumber(double value, PretenureFlag pretenure) {
2094 // Materialize as a SMI if possible.
2095 int32_t int_value;
2096 if (DoubleToSmiInteger(value, &int_value)) {
2097 return handle(Smi::FromInt(int_value), isolate());
2098 }
2099
2100 // Materialize the value in the heap.
2101 return NewHeapNumber(value, IMMUTABLE, pretenure);
2102 }
2103
NewNumberFromInt(int32_t value,PretenureFlag pretenure)2104 Handle<Object> Factory::NewNumberFromInt(int32_t value,
2105 PretenureFlag pretenure) {
2106 if (Smi::IsValid(value)) return handle(Smi::FromInt(value), isolate());
2107 // Bypass NewNumber to avoid various redundant checks.
2108 return NewHeapNumber(FastI2D(value), IMMUTABLE, pretenure);
2109 }
2110
NewNumberFromUint(uint32_t value,PretenureFlag pretenure)2111 Handle<Object> Factory::NewNumberFromUint(uint32_t value,
2112 PretenureFlag pretenure) {
2113 int32_t int32v = static_cast<int32_t>(value);
2114 if (int32v >= 0 && Smi::IsValid(int32v)) {
2115 return handle(Smi::FromInt(int32v), isolate());
2116 }
2117 return NewHeapNumber(FastUI2D(value), IMMUTABLE, pretenure);
2118 }
2119
NewHeapNumber(MutableMode mode,PretenureFlag pretenure)2120 Handle<HeapNumber> Factory::NewHeapNumber(MutableMode mode,
2121 PretenureFlag pretenure) {
2122 STATIC_ASSERT(HeapNumber::kSize <= kMaxRegularHeapObjectSize);
2123 Map* map = mode == MUTABLE ? *mutable_heap_number_map() : *heap_number_map();
2124 HeapObject* result = AllocateRawWithImmortalMap(HeapNumber::kSize, pretenure,
2125 map, kDoubleUnaligned);
2126 return handle(HeapNumber::cast(result), isolate());
2127 }
2128
NewBigInt(int length,PretenureFlag pretenure)2129 Handle<FreshlyAllocatedBigInt> Factory::NewBigInt(int length,
2130 PretenureFlag pretenure) {
2131 if (length < 0 || length > BigInt::kMaxLength) {
2132 isolate()->heap()->FatalProcessOutOfMemory("invalid BigInt length");
2133 }
2134 HeapObject* result = AllocateRawWithImmortalMap(BigInt::SizeFor(length),
2135 pretenure, *bigint_map());
2136 return handle(FreshlyAllocatedBigInt::cast(result), isolate());
2137 }
2138
NewError(Handle<JSFunction> constructor,MessageTemplate::Template template_index,Handle<Object> arg0,Handle<Object> arg1,Handle<Object> arg2)2139 Handle<Object> Factory::NewError(Handle<JSFunction> constructor,
2140 MessageTemplate::Template template_index,
2141 Handle<Object> arg0, Handle<Object> arg1,
2142 Handle<Object> arg2) {
2143 HandleScope scope(isolate());
2144 if (isolate()->bootstrapper()->IsActive()) {
2145 // During bootstrapping we cannot construct error objects.
2146 return scope.CloseAndEscape(NewStringFromAsciiChecked(
2147 MessageTemplate::TemplateString(template_index)));
2148 }
2149
2150 if (arg0.is_null()) arg0 = undefined_value();
2151 if (arg1.is_null()) arg1 = undefined_value();
2152 if (arg2.is_null()) arg2 = undefined_value();
2153
2154 Handle<Object> result;
2155 if (!ErrorUtils::MakeGenericError(isolate(), constructor, template_index,
2156 arg0, arg1, arg2, SKIP_NONE)
2157 .ToHandle(&result)) {
2158 // If an exception is thrown while
2159 // running the factory method, use the exception as the result.
2160 DCHECK(isolate()->has_pending_exception());
2161 result = handle(isolate()->pending_exception(), isolate());
2162 isolate()->clear_pending_exception();
2163 }
2164
2165 return scope.CloseAndEscape(result);
2166 }
2167
NewError(Handle<JSFunction> constructor,Handle<String> message)2168 Handle<Object> Factory::NewError(Handle<JSFunction> constructor,
2169 Handle<String> message) {
2170 // Construct a new error object. If an exception is thrown, use the exception
2171 // as the result.
2172
2173 Handle<Object> no_caller;
2174 MaybeHandle<Object> maybe_error =
2175 ErrorUtils::Construct(isolate(), constructor, constructor, message,
2176 SKIP_NONE, no_caller, false);
2177 if (maybe_error.is_null()) {
2178 DCHECK(isolate()->has_pending_exception());
2179 maybe_error = handle(isolate()->pending_exception(), isolate());
2180 isolate()->clear_pending_exception();
2181 }
2182
2183 return maybe_error.ToHandleChecked();
2184 }
2185
NewInvalidStringLengthError()2186 Handle<Object> Factory::NewInvalidStringLengthError() {
2187 if (FLAG_abort_on_stack_or_string_length_overflow) {
2188 FATAL("Aborting on invalid string length");
2189 }
2190 // Invalidate the "string length" protector.
2191 if (isolate()->IsStringLengthOverflowIntact()) {
2192 isolate()->InvalidateStringLengthOverflowProtector();
2193 }
2194 return NewRangeError(MessageTemplate::kInvalidStringLength);
2195 }
2196
2197 #define DEFINE_ERROR(NAME, name) \
2198 Handle<Object> Factory::New##NAME(MessageTemplate::Template template_index, \
2199 Handle<Object> arg0, Handle<Object> arg1, \
2200 Handle<Object> arg2) { \
2201 return NewError(isolate()->name##_function(), template_index, arg0, arg1, \
2202 arg2); \
2203 }
DEFINE_ERROR(Error,error)2204 DEFINE_ERROR(Error, error)
2205 DEFINE_ERROR(EvalError, eval_error)
2206 DEFINE_ERROR(RangeError, range_error)
2207 DEFINE_ERROR(ReferenceError, reference_error)
2208 DEFINE_ERROR(SyntaxError, syntax_error)
2209 DEFINE_ERROR(TypeError, type_error)
2210 DEFINE_ERROR(WasmCompileError, wasm_compile_error)
2211 DEFINE_ERROR(WasmLinkError, wasm_link_error)
2212 DEFINE_ERROR(WasmRuntimeError, wasm_runtime_error)
2213 #undef DEFINE_ERROR
2214
2215 Handle<JSFunction> Factory::NewFunction(Handle<Map> map,
2216 Handle<SharedFunctionInfo> info,
2217 Handle<Context> context,
2218 PretenureFlag pretenure) {
2219 Handle<JSFunction> function(JSFunction::cast(New(map, pretenure)), isolate());
2220
2221 function->initialize_properties();
2222 function->initialize_elements();
2223 function->set_shared(*info);
2224 function->set_code(info->GetCode());
2225 function->set_context(*context);
2226 function->set_feedback_cell(*many_closures_cell());
2227 int header_size;
2228 if (map->has_prototype_slot()) {
2229 header_size = JSFunction::kSizeWithPrototype;
2230 function->set_prototype_or_initial_map(*the_hole_value());
2231 } else {
2232 header_size = JSFunction::kSizeWithoutPrototype;
2233 }
2234 InitializeJSObjectBody(function, map, header_size);
2235 return function;
2236 }
2237
NewFunctionForTest(Handle<String> name)2238 Handle<JSFunction> Factory::NewFunctionForTest(Handle<String> name) {
2239 NewFunctionArgs args = NewFunctionArgs::ForFunctionWithoutCode(
2240 name, isolate()->sloppy_function_map(), LanguageMode::kSloppy);
2241 Handle<JSFunction> result = NewFunction(args);
2242 DCHECK(is_sloppy(result->shared()->language_mode()));
2243 return result;
2244 }
2245
NewFunction(const NewFunctionArgs & args)2246 Handle<JSFunction> Factory::NewFunction(const NewFunctionArgs& args) {
2247 DCHECK(!args.name_.is_null());
2248
2249 // Create the SharedFunctionInfo.
2250 Handle<Context> context(isolate()->native_context());
2251 Handle<Map> map = args.GetMap(isolate());
2252 Handle<SharedFunctionInfo> info =
2253 NewSharedFunctionInfo(args.name_, args.maybe_exported_function_data_,
2254 args.maybe_builtin_id_, kNormalFunction);
2255
2256 // Proper language mode in shared function info will be set later.
2257 DCHECK(is_sloppy(info->language_mode()));
2258 DCHECK(!map->IsUndefined(isolate()));
2259
2260 #ifdef DEBUG
2261 if (isolate()->bootstrapper()->IsActive()) {
2262 Handle<Code> code;
2263 DCHECK(
2264 // During bootstrapping some of these maps could be not created yet.
2265 (*map == context->get(Context::STRICT_FUNCTION_MAP_INDEX)) ||
2266 (*map ==
2267 context->get(Context::STRICT_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX)) ||
2268 (*map ==
2269 context->get(
2270 Context::STRICT_FUNCTION_WITH_READONLY_PROTOTYPE_MAP_INDEX)) ||
2271 // Check if it's a creation of an empty or Proxy function during
2272 // bootstrapping.
2273 (args.maybe_builtin_id_ == Builtins::kEmptyFunction ||
2274 args.maybe_builtin_id_ == Builtins::kProxyConstructor));
2275 } else {
2276 DCHECK(
2277 (*map == *isolate()->sloppy_function_map()) ||
2278 (*map == *isolate()->sloppy_function_without_prototype_map()) ||
2279 (*map == *isolate()->sloppy_function_with_readonly_prototype_map()) ||
2280 (*map == *isolate()->strict_function_map()) ||
2281 (*map == *isolate()->strict_function_without_prototype_map()) ||
2282 (*map == *isolate()->native_function_map()));
2283 }
2284 #endif
2285
2286 Handle<JSFunction> result = NewFunction(map, info, context);
2287
2288 if (args.should_set_prototype_) {
2289 result->set_prototype_or_initial_map(
2290 *args.maybe_prototype_.ToHandleChecked());
2291 }
2292
2293 if (args.should_set_language_mode_) {
2294 result->shared()->set_language_mode(args.language_mode_);
2295 }
2296
2297 if (args.should_create_and_set_initial_map_) {
2298 ElementsKind elements_kind;
2299 switch (args.type_) {
2300 case JS_ARRAY_TYPE:
2301 elements_kind = PACKED_SMI_ELEMENTS;
2302 break;
2303 case JS_ARGUMENTS_TYPE:
2304 elements_kind = PACKED_ELEMENTS;
2305 break;
2306 default:
2307 elements_kind = TERMINAL_FAST_ELEMENTS_KIND;
2308 break;
2309 }
2310 Handle<Map> initial_map = NewMap(args.type_, args.instance_size_,
2311 elements_kind, args.inobject_properties_);
2312 result->shared()->set_expected_nof_properties(args.inobject_properties_);
2313 // TODO(littledan): Why do we have this is_generator test when
2314 // NewFunctionPrototype already handles finding an appropriately
2315 // shared prototype?
2316 Handle<Object> prototype = args.maybe_prototype_.ToHandleChecked();
2317 if (!IsResumableFunction(result->shared()->kind())) {
2318 if (prototype->IsTheHole(isolate())) {
2319 prototype = NewFunctionPrototype(result);
2320 }
2321 }
2322 JSFunction::SetInitialMap(result, initial_map, prototype);
2323 }
2324
2325 return result;
2326 }
2327
NewFunctionPrototype(Handle<JSFunction> function)2328 Handle<JSObject> Factory::NewFunctionPrototype(Handle<JSFunction> function) {
2329 // Make sure to use globals from the function's context, since the function
2330 // can be from a different context.
2331 Handle<Context> native_context(function->context()->native_context());
2332 Handle<Map> new_map;
2333 if (V8_UNLIKELY(IsAsyncGeneratorFunction(function->shared()->kind()))) {
2334 new_map = handle(native_context->async_generator_object_prototype_map());
2335 } else if (IsResumableFunction(function->shared()->kind())) {
2336 // Generator and async function prototypes can share maps since they
2337 // don't have "constructor" properties.
2338 new_map = handle(native_context->generator_object_prototype_map());
2339 } else {
2340 // Each function prototype gets a fresh map to avoid unwanted sharing of
2341 // maps between prototypes of different constructors.
2342 Handle<JSFunction> object_function(native_context->object_function());
2343 DCHECK(object_function->has_initial_map());
2344 new_map = handle(object_function->initial_map());
2345 }
2346
2347 DCHECK(!new_map->is_prototype_map());
2348 Handle<JSObject> prototype = NewJSObjectFromMap(new_map);
2349
2350 if (!IsResumableFunction(function->shared()->kind())) {
2351 JSObject::AddProperty(prototype, constructor_string(), function, DONT_ENUM);
2352 }
2353
2354 return prototype;
2355 }
2356
NewFunctionFromSharedFunctionInfo(Handle<SharedFunctionInfo> info,Handle<Context> context,PretenureFlag pretenure)2357 Handle<JSFunction> Factory::NewFunctionFromSharedFunctionInfo(
2358 Handle<SharedFunctionInfo> info, Handle<Context> context,
2359 PretenureFlag pretenure) {
2360 Handle<Map> initial_map(
2361 Map::cast(context->native_context()->get(info->function_map_index())));
2362 return NewFunctionFromSharedFunctionInfo(initial_map, info, context,
2363 pretenure);
2364 }
2365
NewFunctionFromSharedFunctionInfo(Handle<SharedFunctionInfo> info,Handle<Context> context,Handle<FeedbackCell> feedback_cell,PretenureFlag pretenure)2366 Handle<JSFunction> Factory::NewFunctionFromSharedFunctionInfo(
2367 Handle<SharedFunctionInfo> info, Handle<Context> context,
2368 Handle<FeedbackCell> feedback_cell, PretenureFlag pretenure) {
2369 Handle<Map> initial_map(
2370 Map::cast(context->native_context()->get(info->function_map_index())));
2371 return NewFunctionFromSharedFunctionInfo(initial_map, info, context,
2372 feedback_cell, pretenure);
2373 }
2374
NewFunctionFromSharedFunctionInfo(Handle<Map> initial_map,Handle<SharedFunctionInfo> info,Handle<Context> context,PretenureFlag pretenure)2375 Handle<JSFunction> Factory::NewFunctionFromSharedFunctionInfo(
2376 Handle<Map> initial_map, Handle<SharedFunctionInfo> info,
2377 Handle<Context> context, PretenureFlag pretenure) {
2378 DCHECK_EQ(JS_FUNCTION_TYPE, initial_map->instance_type());
2379 Handle<JSFunction> result =
2380 NewFunction(initial_map, info, context, pretenure);
2381
2382 // Give compiler a chance to pre-initialize.
2383 Compiler::PostInstantiation(result, pretenure);
2384
2385 return result;
2386 }
2387
NewFunctionFromSharedFunctionInfo(Handle<Map> initial_map,Handle<SharedFunctionInfo> info,Handle<Context> context,Handle<FeedbackCell> feedback_cell,PretenureFlag pretenure)2388 Handle<JSFunction> Factory::NewFunctionFromSharedFunctionInfo(
2389 Handle<Map> initial_map, Handle<SharedFunctionInfo> info,
2390 Handle<Context> context, Handle<FeedbackCell> feedback_cell,
2391 PretenureFlag pretenure) {
2392 DCHECK_EQ(JS_FUNCTION_TYPE, initial_map->instance_type());
2393 Handle<JSFunction> result =
2394 NewFunction(initial_map, info, context, pretenure);
2395
2396 // Bump the closure count that is encoded in the feedback cell's map.
2397 if (feedback_cell->map() == *no_closures_cell_map()) {
2398 feedback_cell->set_map(*one_closure_cell_map());
2399 } else if (feedback_cell->map() == *one_closure_cell_map()) {
2400 feedback_cell->set_map(*many_closures_cell_map());
2401 } else {
2402 DCHECK_EQ(feedback_cell->map(), *many_closures_cell_map());
2403 }
2404
2405 // Check that the optimized code in the feedback cell wasn't marked for
2406 // deoptimization while not pointed to by any live JSFunction.
2407 if (feedback_cell->value()->IsFeedbackVector()) {
2408 FeedbackVector::cast(feedback_cell->value())
2409 ->EvictOptimizedCodeMarkedForDeoptimization(
2410 *info, "new function from shared function info");
2411 }
2412 result->set_feedback_cell(*feedback_cell);
2413
2414 // Give compiler a chance to pre-initialize.
2415 Compiler::PostInstantiation(result, pretenure);
2416
2417 return result;
2418 }
2419
NewScopeInfo(int length)2420 Handle<ScopeInfo> Factory::NewScopeInfo(int length) {
2421 return NewFixedArrayWithMap<ScopeInfo>(Heap::kScopeInfoMapRootIndex, length,
2422 TENURED);
2423 }
2424
NewModuleInfo()2425 Handle<ModuleInfo> Factory::NewModuleInfo() {
2426 return NewFixedArrayWithMap<ModuleInfo>(Heap::kModuleInfoMapRootIndex,
2427 ModuleInfo::kLength, TENURED);
2428 }
2429
NewPreParsedScopeData()2430 Handle<PreParsedScopeData> Factory::NewPreParsedScopeData() {
2431 Handle<PreParsedScopeData> result =
2432 Handle<PreParsedScopeData>::cast(NewStruct(TUPLE2_TYPE, TENURED));
2433 result->set_scope_data(PodArray<uint8_t>::cast(*empty_byte_array()));
2434 result->set_child_data(*empty_fixed_array());
2435 return result;
2436 }
2437
NewExternal(void * value)2438 Handle<JSObject> Factory::NewExternal(void* value) {
2439 Handle<Foreign> foreign = NewForeign(reinterpret_cast<Address>(value));
2440 Handle<JSObject> external = NewJSObjectFromMap(external_map());
2441 external->SetEmbedderField(0, *foreign);
2442 return external;
2443 }
2444
NewCodeDataContainer(int flags)2445 Handle<CodeDataContainer> Factory::NewCodeDataContainer(int flags) {
2446 Handle<CodeDataContainer> data_container(
2447 CodeDataContainer::cast(New(code_data_container_map(), TENURED)),
2448 isolate());
2449 data_container->set_next_code_link(*undefined_value(), SKIP_WRITE_BARRIER);
2450 data_container->set_kind_specific_flags(flags);
2451 data_container->clear_padding();
2452 return data_container;
2453 }
2454
TryNewCode(const CodeDesc & desc,Code::Kind kind,Handle<Object> self_ref,int32_t builtin_index,MaybeHandle<ByteArray> maybe_source_position_table,MaybeHandle<DeoptimizationData> maybe_deopt_data,Movability movability,uint32_t stub_key,bool is_turbofanned,int stack_slots,int safepoint_table_offset,int handler_table_offset)2455 MaybeHandle<Code> Factory::TryNewCode(
2456 const CodeDesc& desc, Code::Kind kind, Handle<Object> self_ref,
2457 int32_t builtin_index, MaybeHandle<ByteArray> maybe_source_position_table,
2458 MaybeHandle<DeoptimizationData> maybe_deopt_data, Movability movability,
2459 uint32_t stub_key, bool is_turbofanned, int stack_slots,
2460 int safepoint_table_offset, int handler_table_offset) {
2461 // Allocate objects needed for code initialization.
2462 Handle<ByteArray> reloc_info = NewByteArray(desc.reloc_size, TENURED);
2463 Handle<CodeDataContainer> data_container = NewCodeDataContainer(0);
2464 Handle<ByteArray> source_position_table =
2465 maybe_source_position_table.is_null()
2466 ? empty_byte_array()
2467 : maybe_source_position_table.ToHandleChecked();
2468 Handle<DeoptimizationData> deopt_data =
2469 maybe_deopt_data.is_null() ? DeoptimizationData::Empty(isolate())
2470 : maybe_deopt_data.ToHandleChecked();
2471 Handle<Code> code;
2472 {
2473 int object_size = ComputeCodeObjectSize(desc);
2474
2475 Heap* heap = isolate()->heap();
2476 CodePageCollectionMemoryModificationScope code_allocation(heap);
2477 HeapObject* result =
2478 heap->AllocateRawWithLigthRetry(object_size, CODE_SPACE);
2479
2480 // Return an empty handle if we cannot allocate the code object.
2481 if (!result) return MaybeHandle<Code>();
2482
2483 if (movability == kImmovable) {
2484 result = heap->EnsureImmovableCode(result, object_size);
2485 }
2486
2487 // The code object has not been fully initialized yet. We rely on the
2488 // fact that no allocation will happen from this point on.
2489 DisallowHeapAllocation no_gc;
2490
2491 result->set_map_after_allocation(*code_map(), SKIP_WRITE_BARRIER);
2492 code = handle(Code::cast(result), isolate());
2493
2494 InitializeCode(code, object_size, desc, kind, self_ref, builtin_index,
2495 source_position_table, deopt_data, reloc_info,
2496 data_container, stub_key, is_turbofanned, stack_slots,
2497 safepoint_table_offset, handler_table_offset);
2498 }
2499 // Flush the instruction cache after changing the permissions.
2500 code->FlushICache();
2501
2502 return code;
2503 }
2504
NewCode(const CodeDesc & desc,Code::Kind kind,Handle<Object> self_ref,int32_t builtin_index,MaybeHandle<ByteArray> maybe_source_position_table,MaybeHandle<DeoptimizationData> maybe_deopt_data,Movability movability,uint32_t stub_key,bool is_turbofanned,int stack_slots,int safepoint_table_offset,int handler_table_offset)2505 Handle<Code> Factory::NewCode(
2506 const CodeDesc& desc, Code::Kind kind, Handle<Object> self_ref,
2507 int32_t builtin_index, MaybeHandle<ByteArray> maybe_source_position_table,
2508 MaybeHandle<DeoptimizationData> maybe_deopt_data, Movability movability,
2509 uint32_t stub_key, bool is_turbofanned, int stack_slots,
2510 int safepoint_table_offset, int handler_table_offset) {
2511 // Allocate objects needed for code initialization.
2512 Handle<ByteArray> reloc_info = NewByteArray(desc.reloc_size, TENURED);
2513 Handle<CodeDataContainer> data_container = NewCodeDataContainer(0);
2514 Handle<ByteArray> source_position_table =
2515 maybe_source_position_table.is_null()
2516 ? empty_byte_array()
2517 : maybe_source_position_table.ToHandleChecked();
2518 Handle<DeoptimizationData> deopt_data =
2519 maybe_deopt_data.is_null() ? DeoptimizationData::Empty(isolate())
2520 : maybe_deopt_data.ToHandleChecked();
2521
2522 Handle<Code> code;
2523 {
2524 int object_size = ComputeCodeObjectSize(desc);
2525
2526 Heap* heap = isolate()->heap();
2527 CodePageCollectionMemoryModificationScope code_allocation(heap);
2528 HeapObject* result =
2529 heap->AllocateRawWithRetryOrFail(object_size, CODE_SPACE);
2530
2531 if (movability == kImmovable) {
2532 result = heap->EnsureImmovableCode(result, object_size);
2533 }
2534
2535 // The code object has not been fully initialized yet. We rely on the
2536 // fact that no allocation will happen from this point on.
2537 DisallowHeapAllocation no_gc;
2538
2539 result->set_map_after_allocation(*code_map(), SKIP_WRITE_BARRIER);
2540 code = handle(Code::cast(result), isolate());
2541
2542 InitializeCode(code, object_size, desc, kind, self_ref, builtin_index,
2543 source_position_table, deopt_data, reloc_info,
2544 data_container, stub_key, is_turbofanned, stack_slots,
2545 safepoint_table_offset, handler_table_offset);
2546 }
2547 // Flush the instruction cache after changing the permissions.
2548 code->FlushICache();
2549
2550 return code;
2551 }
2552
NewCodeForDeserialization(uint32_t size)2553 Handle<Code> Factory::NewCodeForDeserialization(uint32_t size) {
2554 DCHECK(IsAligned(static_cast<intptr_t>(size), kCodeAlignment));
2555 Heap* heap = isolate()->heap();
2556 HeapObject* result = heap->AllocateRawWithRetryOrFail(size, CODE_SPACE);
2557 // Unprotect the memory chunk of the object if it was not unprotected
2558 // already.
2559 heap->UnprotectAndRegisterMemoryChunk(result);
2560 heap->ZapCodeObject(result->address(), size);
2561 result->set_map_after_allocation(*code_map(), SKIP_WRITE_BARRIER);
2562 DCHECK(IsAligned(result->address(), kCodeAlignment));
2563 DCHECK(!heap->memory_allocator()->code_range()->valid() ||
2564 heap->memory_allocator()->code_range()->contains(result->address()) ||
2565 static_cast<int>(size) <= heap->code_space()->AreaSize());
2566 return handle(Code::cast(result), isolate());
2567 }
2568
2569 #ifdef V8_EMBEDDED_BUILTINS
NewOffHeapTrampolineFor(Handle<Code> code,Address off_heap_entry)2570 Handle<Code> Factory::NewOffHeapTrampolineFor(Handle<Code> code,
2571 Address off_heap_entry) {
2572 DCHECK(isolate()->serializer_enabled());
2573 DCHECK_NOT_NULL(isolate()->embedded_blob());
2574 DCHECK_NE(0, isolate()->embedded_blob_size());
2575 DCHECK(Builtins::IsEmbeddedBuiltin(*code));
2576
2577 Handle<Code> result =
2578 Builtins::GenerateOffHeapTrampolineFor(isolate(), off_heap_entry);
2579
2580 // The trampoline code object must inherit specific flags from the original
2581 // builtin (e.g. the safepoint-table offset). We set them manually here.
2582
2583 const int stack_slots = code->has_safepoint_info() ? code->stack_slots() : 0;
2584 result->initialize_flags(code->kind(), code->has_unwinding_info(),
2585 code->is_turbofanned(), stack_slots);
2586 result->set_builtin_index(code->builtin_index());
2587 result->set_handler_table_offset(code->handler_table_offset());
2588 result->code_data_container()->set_kind_specific_flags(
2589 code->code_data_container()->kind_specific_flags());
2590 result->set_constant_pool_offset(code->constant_pool_offset());
2591 if (code->has_safepoint_info()) {
2592 result->set_safepoint_table_offset(code->safepoint_table_offset());
2593 }
2594
2595 return result;
2596 }
2597 #endif
2598
CopyCode(Handle<Code> code)2599 Handle<Code> Factory::CopyCode(Handle<Code> code) {
2600 Handle<CodeDataContainer> data_container =
2601 NewCodeDataContainer(code->code_data_container()->kind_specific_flags());
2602
2603 Heap* heap = isolate()->heap();
2604 int obj_size = code->Size();
2605 HeapObject* result = heap->AllocateRawWithRetryOrFail(obj_size, CODE_SPACE);
2606
2607 // Copy code object.
2608 Address old_addr = code->address();
2609 Address new_addr = result->address();
2610 Heap::CopyBlock(new_addr, old_addr, obj_size);
2611 Handle<Code> new_code(Code::cast(result), isolate());
2612
2613 // Set the {CodeDataContainer}, it cannot be shared.
2614 new_code->set_code_data_container(*data_container);
2615
2616 new_code->Relocate(new_addr - old_addr);
2617 // We have to iterate over the object and process its pointers when black
2618 // allocation is on.
2619 heap->incremental_marking()->ProcessBlackAllocatedObject(*new_code);
2620 // Record all references to embedded objects in the new code object.
2621 heap->RecordWritesIntoCode(*new_code);
2622
2623 #ifdef VERIFY_HEAP
2624 if (FLAG_verify_heap) new_code->ObjectVerify();
2625 #endif
2626 DCHECK(IsAligned(new_code->address(), kCodeAlignment));
2627 DCHECK(
2628 !heap->memory_allocator()->code_range()->valid() ||
2629 heap->memory_allocator()->code_range()->contains(new_code->address()) ||
2630 obj_size <= heap->code_space()->AreaSize());
2631 return new_code;
2632 }
2633
CopyBytecodeArray(Handle<BytecodeArray> bytecode_array)2634 Handle<BytecodeArray> Factory::CopyBytecodeArray(
2635 Handle<BytecodeArray> bytecode_array) {
2636 int size = BytecodeArray::SizeFor(bytecode_array->length());
2637 HeapObject* result =
2638 AllocateRawWithImmortalMap(size, TENURED, *bytecode_array_map());
2639
2640 Handle<BytecodeArray> copy(BytecodeArray::cast(result), isolate());
2641 copy->set_length(bytecode_array->length());
2642 copy->set_frame_size(bytecode_array->frame_size());
2643 copy->set_parameter_count(bytecode_array->parameter_count());
2644 copy->set_incoming_new_target_or_generator_register(
2645 bytecode_array->incoming_new_target_or_generator_register());
2646 copy->set_constant_pool(bytecode_array->constant_pool());
2647 copy->set_handler_table(bytecode_array->handler_table());
2648 copy->set_source_position_table(bytecode_array->source_position_table());
2649 copy->set_interrupt_budget(bytecode_array->interrupt_budget());
2650 copy->set_osr_loop_nesting_level(bytecode_array->osr_loop_nesting_level());
2651 copy->set_bytecode_age(bytecode_array->bytecode_age());
2652 bytecode_array->CopyBytecodesTo(*copy);
2653 return copy;
2654 }
2655
NewJSObject(Handle<JSFunction> constructor,PretenureFlag pretenure)2656 Handle<JSObject> Factory::NewJSObject(Handle<JSFunction> constructor,
2657 PretenureFlag pretenure) {
2658 JSFunction::EnsureHasInitialMap(constructor);
2659 Handle<Map> map(constructor->initial_map());
2660 return NewJSObjectFromMap(map, pretenure);
2661 }
2662
NewJSObjectWithNullProto(PretenureFlag pretenure)2663 Handle<JSObject> Factory::NewJSObjectWithNullProto(PretenureFlag pretenure) {
2664 Handle<JSObject> result =
2665 NewJSObject(isolate()->object_function(), pretenure);
2666 Handle<Map> new_map =
2667 Map::Copy(Handle<Map>(result->map()), "ObjectWithNullProto");
2668 Map::SetPrototype(new_map, null_value());
2669 JSObject::MigrateToMap(result, new_map);
2670 return result;
2671 }
2672
NewJSGlobalObject(Handle<JSFunction> constructor)2673 Handle<JSGlobalObject> Factory::NewJSGlobalObject(
2674 Handle<JSFunction> constructor) {
2675 DCHECK(constructor->has_initial_map());
2676 Handle<Map> map(constructor->initial_map());
2677 DCHECK(map->is_dictionary_map());
2678
2679 // Make sure no field properties are described in the initial map.
2680 // This guarantees us that normalizing the properties does not
2681 // require us to change property values to PropertyCells.
2682 DCHECK_EQ(map->NextFreePropertyIndex(), 0);
2683
2684 // Make sure we don't have a ton of pre-allocated slots in the
2685 // global objects. They will be unused once we normalize the object.
2686 DCHECK_EQ(map->UnusedPropertyFields(), 0);
2687 DCHECK_EQ(map->GetInObjectProperties(), 0);
2688
2689 // Initial size of the backing store to avoid resize of the storage during
2690 // bootstrapping. The size differs between the JS global object ad the
2691 // builtins object.
2692 int initial_size = 64;
2693
2694 // Allocate a dictionary object for backing storage.
2695 int at_least_space_for = map->NumberOfOwnDescriptors() * 2 + initial_size;
2696 Handle<GlobalDictionary> dictionary =
2697 GlobalDictionary::New(isolate(), at_least_space_for);
2698
2699 // The global object might be created from an object template with accessors.
2700 // Fill these accessors into the dictionary.
2701 Handle<DescriptorArray> descs(map->instance_descriptors());
2702 for (int i = 0; i < map->NumberOfOwnDescriptors(); i++) {
2703 PropertyDetails details = descs->GetDetails(i);
2704 // Only accessors are expected.
2705 DCHECK_EQ(kAccessor, details.kind());
2706 PropertyDetails d(kAccessor, details.attributes(),
2707 PropertyCellType::kMutable);
2708 Handle<Name> name(descs->GetKey(i));
2709 Handle<PropertyCell> cell = NewPropertyCell(name);
2710 cell->set_value(descs->GetValue(i));
2711 // |dictionary| already contains enough space for all properties.
2712 USE(GlobalDictionary::Add(dictionary, name, cell, d));
2713 }
2714
2715 // Allocate the global object and initialize it with the backing store.
2716 Handle<JSGlobalObject> global(JSGlobalObject::cast(New(map, TENURED)),
2717 isolate());
2718 InitializeJSObjectFromMap(global, dictionary, map);
2719
2720 // Create a new map for the global object.
2721 Handle<Map> new_map = Map::CopyDropDescriptors(map);
2722 new_map->set_may_have_interesting_symbols(true);
2723 new_map->set_is_dictionary_map(true);
2724
2725 // Set up the global object as a normalized object.
2726 global->set_global_dictionary(*dictionary);
2727 global->synchronized_set_map(*new_map);
2728
2729 // Make sure result is a global object with properties in dictionary.
2730 DCHECK(global->IsJSGlobalObject() && !global->HasFastProperties());
2731 return global;
2732 }
2733
InitializeJSObjectFromMap(Handle<JSObject> obj,Handle<Object> properties,Handle<Map> map)2734 void Factory::InitializeJSObjectFromMap(Handle<JSObject> obj,
2735 Handle<Object> properties,
2736 Handle<Map> map) {
2737 obj->set_raw_properties_or_hash(*properties);
2738 obj->initialize_elements();
2739 // TODO(1240798): Initialize the object's body using valid initial values
2740 // according to the object's initial map. For example, if the map's
2741 // instance type is JS_ARRAY_TYPE, the length field should be initialized
2742 // to a number (e.g. Smi::kZero) and the elements initialized to a
2743 // fixed array (e.g. Heap::empty_fixed_array()). Currently, the object
2744 // verification code has to cope with (temporarily) invalid objects. See
2745 // for example, JSArray::JSArrayVerify).
2746 InitializeJSObjectBody(obj, map, JSObject::kHeaderSize);
2747 }
2748
InitializeJSObjectBody(Handle<JSObject> obj,Handle<Map> map,int start_offset)2749 void Factory::InitializeJSObjectBody(Handle<JSObject> obj, Handle<Map> map,
2750 int start_offset) {
2751 if (start_offset == map->instance_size()) return;
2752 DCHECK_LT(start_offset, map->instance_size());
2753
2754 // We cannot always fill with one_pointer_filler_map because objects
2755 // created from API functions expect their embedder fields to be initialized
2756 // with undefined_value.
2757 // Pre-allocated fields need to be initialized with undefined_value as well
2758 // so that object accesses before the constructor completes (e.g. in the
2759 // debugger) will not cause a crash.
2760
2761 // In case of Array subclassing the |map| could already be transitioned
2762 // to different elements kind from the initial map on which we track slack.
2763 bool in_progress = map->IsInobjectSlackTrackingInProgress();
2764 Object* filler;
2765 if (in_progress) {
2766 filler = *one_pointer_filler_map();
2767 } else {
2768 filler = *undefined_value();
2769 }
2770 obj->InitializeBody(*map, start_offset, *undefined_value(), filler);
2771 if (in_progress) {
2772 map->FindRootMap()->InobjectSlackTrackingStep();
2773 }
2774 }
2775
NewJSObjectFromMap(Handle<Map> map,PretenureFlag pretenure,Handle<AllocationSite> allocation_site)2776 Handle<JSObject> Factory::NewJSObjectFromMap(
2777 Handle<Map> map, PretenureFlag pretenure,
2778 Handle<AllocationSite> allocation_site) {
2779 // JSFunctions should be allocated using AllocateFunction to be
2780 // properly initialized.
2781 DCHECK(map->instance_type() != JS_FUNCTION_TYPE);
2782
2783 // Both types of global objects should be allocated using
2784 // AllocateGlobalObject to be properly initialized.
2785 DCHECK(map->instance_type() != JS_GLOBAL_OBJECT_TYPE);
2786
2787 HeapObject* obj =
2788 AllocateRawWithAllocationSite(map, pretenure, allocation_site);
2789 Handle<JSObject> js_obj(JSObject::cast(obj), isolate());
2790
2791 InitializeJSObjectFromMap(js_obj, empty_fixed_array(), map);
2792
2793 DCHECK(js_obj->HasFastElements() || js_obj->HasFixedTypedArrayElements() ||
2794 js_obj->HasFastStringWrapperElements() ||
2795 js_obj->HasFastArgumentsElements());
2796 return js_obj;
2797 }
2798
NewSlowJSObjectFromMap(Handle<Map> map,int capacity,PretenureFlag pretenure)2799 Handle<JSObject> Factory::NewSlowJSObjectFromMap(Handle<Map> map, int capacity,
2800 PretenureFlag pretenure) {
2801 DCHECK(map->is_dictionary_map());
2802 Handle<NameDictionary> object_properties =
2803 NameDictionary::New(isolate(), capacity);
2804 Handle<JSObject> js_object = NewJSObjectFromMap(map, pretenure);
2805 js_object->set_raw_properties_or_hash(*object_properties);
2806 return js_object;
2807 }
2808
NewJSArray(ElementsKind elements_kind,PretenureFlag pretenure)2809 Handle<JSArray> Factory::NewJSArray(ElementsKind elements_kind,
2810 PretenureFlag pretenure) {
2811 Context* native_context = isolate()->raw_native_context();
2812 Map* map = native_context->GetInitialJSArrayMap(elements_kind);
2813 if (map == nullptr) {
2814 JSFunction* array_function = native_context->array_function();
2815 map = array_function->initial_map();
2816 }
2817 return Handle<JSArray>::cast(NewJSObjectFromMap(handle(map), pretenure));
2818 }
2819
NewJSArray(ElementsKind elements_kind,int length,int capacity,ArrayStorageAllocationMode mode,PretenureFlag pretenure)2820 Handle<JSArray> Factory::NewJSArray(ElementsKind elements_kind, int length,
2821 int capacity,
2822 ArrayStorageAllocationMode mode,
2823 PretenureFlag pretenure) {
2824 Handle<JSArray> array = NewJSArray(elements_kind, pretenure);
2825 NewJSArrayStorage(array, length, capacity, mode);
2826 return array;
2827 }
2828
NewJSArrayWithElements(Handle<FixedArrayBase> elements,ElementsKind elements_kind,int length,PretenureFlag pretenure)2829 Handle<JSArray> Factory::NewJSArrayWithElements(Handle<FixedArrayBase> elements,
2830 ElementsKind elements_kind,
2831 int length,
2832 PretenureFlag pretenure) {
2833 DCHECK(length <= elements->length());
2834 Handle<JSArray> array = NewJSArray(elements_kind, pretenure);
2835
2836 array->set_elements(*elements);
2837 array->set_length(Smi::FromInt(length));
2838 JSObject::ValidateElements(*array);
2839 return array;
2840 }
2841
NewJSArrayStorage(Handle<JSArray> array,int length,int capacity,ArrayStorageAllocationMode mode)2842 void Factory::NewJSArrayStorage(Handle<JSArray> array, int length, int capacity,
2843 ArrayStorageAllocationMode mode) {
2844 DCHECK(capacity >= length);
2845
2846 if (capacity == 0) {
2847 array->set_length(Smi::kZero);
2848 array->set_elements(*empty_fixed_array());
2849 return;
2850 }
2851
2852 HandleScope inner_scope(isolate());
2853 Handle<FixedArrayBase> elms;
2854 ElementsKind elements_kind = array->GetElementsKind();
2855 if (IsDoubleElementsKind(elements_kind)) {
2856 if (mode == DONT_INITIALIZE_ARRAY_ELEMENTS) {
2857 elms = NewFixedDoubleArray(capacity);
2858 } else {
2859 DCHECK(mode == INITIALIZE_ARRAY_ELEMENTS_WITH_HOLE);
2860 elms = NewFixedDoubleArrayWithHoles(capacity);
2861 }
2862 } else {
2863 DCHECK(IsSmiOrObjectElementsKind(elements_kind));
2864 if (mode == DONT_INITIALIZE_ARRAY_ELEMENTS) {
2865 elms = NewUninitializedFixedArray(capacity);
2866 } else {
2867 DCHECK(mode == INITIALIZE_ARRAY_ELEMENTS_WITH_HOLE);
2868 elms = NewFixedArrayWithHoles(capacity);
2869 }
2870 }
2871
2872 array->set_elements(*elms);
2873 array->set_length(Smi::FromInt(length));
2874 }
2875
NewJSWeakMap()2876 Handle<JSWeakMap> Factory::NewJSWeakMap() {
2877 Context* native_context = isolate()->raw_native_context();
2878 Handle<Map> map(native_context->js_weak_map_fun()->initial_map());
2879 Handle<JSWeakMap> weakmap(JSWeakMap::cast(*NewJSObjectFromMap(map)));
2880 {
2881 // Do not leak handles for the hash table, it would make entries strong.
2882 HandleScope scope(isolate());
2883 JSWeakCollection::Initialize(weakmap, isolate());
2884 }
2885 return weakmap;
2886 }
2887
NewJSModuleNamespace()2888 Handle<JSModuleNamespace> Factory::NewJSModuleNamespace() {
2889 Handle<Map> map = isolate()->js_module_namespace_map();
2890 Handle<JSModuleNamespace> module_namespace(
2891 Handle<JSModuleNamespace>::cast(NewJSObjectFromMap(map)));
2892 FieldIndex index = FieldIndex::ForDescriptor(
2893 *map, JSModuleNamespace::kToStringTagFieldIndex);
2894 module_namespace->FastPropertyAtPut(index,
2895 isolate()->heap()->Module_string());
2896 return module_namespace;
2897 }
2898
NewJSGeneratorObject(Handle<JSFunction> function)2899 Handle<JSGeneratorObject> Factory::NewJSGeneratorObject(
2900 Handle<JSFunction> function) {
2901 DCHECK(IsResumableFunction(function->shared()->kind()));
2902 JSFunction::EnsureHasInitialMap(function);
2903 Handle<Map> map(function->initial_map());
2904
2905 DCHECK(map->instance_type() == JS_GENERATOR_OBJECT_TYPE ||
2906 map->instance_type() == JS_ASYNC_GENERATOR_OBJECT_TYPE);
2907
2908 return Handle<JSGeneratorObject>::cast(NewJSObjectFromMap(map));
2909 }
2910
NewModule(Handle<SharedFunctionInfo> code)2911 Handle<Module> Factory::NewModule(Handle<SharedFunctionInfo> code) {
2912 Handle<ModuleInfo> module_info(code->scope_info()->ModuleDescriptorInfo(),
2913 isolate());
2914 Handle<ObjectHashTable> exports =
2915 ObjectHashTable::New(isolate(), module_info->RegularExportCount());
2916 Handle<FixedArray> regular_exports =
2917 NewFixedArray(module_info->RegularExportCount());
2918 Handle<FixedArray> regular_imports =
2919 NewFixedArray(module_info->regular_imports()->length());
2920 int requested_modules_length = module_info->module_requests()->length();
2921 Handle<FixedArray> requested_modules =
2922 requested_modules_length > 0 ? NewFixedArray(requested_modules_length)
2923 : empty_fixed_array();
2924
2925 Handle<Module> module = Handle<Module>::cast(NewStruct(MODULE_TYPE, TENURED));
2926 module->set_code(*code);
2927 module->set_exports(*exports);
2928 module->set_regular_exports(*regular_exports);
2929 module->set_regular_imports(*regular_imports);
2930 module->set_hash(isolate()->GenerateIdentityHash(Smi::kMaxValue));
2931 module->set_module_namespace(isolate()->heap()->undefined_value());
2932 module->set_requested_modules(*requested_modules);
2933 module->set_script(Script::cast(code->script()));
2934 module->set_status(Module::kUninstantiated);
2935 module->set_exception(isolate()->heap()->the_hole_value());
2936 module->set_import_meta(isolate()->heap()->the_hole_value());
2937 module->set_dfs_index(-1);
2938 module->set_dfs_ancestor_index(-1);
2939 return module;
2940 }
2941
NewJSArrayBuffer(SharedFlag shared,PretenureFlag pretenure)2942 Handle<JSArrayBuffer> Factory::NewJSArrayBuffer(SharedFlag shared,
2943 PretenureFlag pretenure) {
2944 Handle<JSFunction> array_buffer_fun(
2945 shared == SharedFlag::kShared
2946 ? isolate()->native_context()->shared_array_buffer_fun()
2947 : isolate()->native_context()->array_buffer_fun());
2948 Handle<Map> map(array_buffer_fun->initial_map(), isolate());
2949 return Handle<JSArrayBuffer>::cast(NewJSObjectFromMap(map, pretenure));
2950 }
2951
NewJSIteratorResult(Handle<Object> value,bool done)2952 Handle<JSIteratorResult> Factory::NewJSIteratorResult(Handle<Object> value,
2953 bool done) {
2954 Handle<Map> map(isolate()->native_context()->iterator_result_map());
2955 Handle<JSIteratorResult> js_iter_result =
2956 Handle<JSIteratorResult>::cast(NewJSObjectFromMap(map));
2957 js_iter_result->set_value(*value);
2958 js_iter_result->set_done(*ToBoolean(done));
2959 return js_iter_result;
2960 }
2961
NewJSAsyncFromSyncIterator(Handle<JSReceiver> sync_iterator,Handle<Object> next)2962 Handle<JSAsyncFromSyncIterator> Factory::NewJSAsyncFromSyncIterator(
2963 Handle<JSReceiver> sync_iterator, Handle<Object> next) {
2964 Handle<Map> map(isolate()->native_context()->async_from_sync_iterator_map());
2965 Handle<JSAsyncFromSyncIterator> iterator =
2966 Handle<JSAsyncFromSyncIterator>::cast(NewJSObjectFromMap(map));
2967
2968 iterator->set_sync_iterator(*sync_iterator);
2969 iterator->set_next(*next);
2970 return iterator;
2971 }
2972
NewJSMap()2973 Handle<JSMap> Factory::NewJSMap() {
2974 Handle<Map> map(isolate()->native_context()->js_map_map());
2975 Handle<JSMap> js_map = Handle<JSMap>::cast(NewJSObjectFromMap(map));
2976 JSMap::Initialize(js_map, isolate());
2977 return js_map;
2978 }
2979
NewJSSet()2980 Handle<JSSet> Factory::NewJSSet() {
2981 Handle<Map> map(isolate()->native_context()->js_set_map());
2982 Handle<JSSet> js_set = Handle<JSSet>::cast(NewJSObjectFromMap(map));
2983 JSSet::Initialize(js_set, isolate());
2984 return js_set;
2985 }
2986
NewJSMapIterator(Handle<Map> map,Handle<OrderedHashMap> table,int index)2987 Handle<JSMapIterator> Factory::NewJSMapIterator(Handle<Map> map,
2988 Handle<OrderedHashMap> table,
2989 int index) {
2990 Handle<JSMapIterator> result =
2991 Handle<JSMapIterator>::cast(NewJSObjectFromMap(map));
2992 result->set_table(*table);
2993 result->set_index(Smi::FromInt(index));
2994 return result;
2995 }
2996
NewJSSetIterator(Handle<Map> map,Handle<OrderedHashSet> table,int index)2997 Handle<JSSetIterator> Factory::NewJSSetIterator(Handle<Map> map,
2998 Handle<OrderedHashSet> table,
2999 int index) {
3000 Handle<JSSetIterator> result =
3001 Handle<JSSetIterator>::cast(NewJSObjectFromMap(map));
3002 result->set_table(*table);
3003 result->set_index(Smi::FromInt(index));
3004 return result;
3005 }
3006
TypeAndSizeForElementsKind(ElementsKind kind,ExternalArrayType * array_type,size_t * element_size)3007 void Factory::TypeAndSizeForElementsKind(ElementsKind kind,
3008 ExternalArrayType* array_type,
3009 size_t* element_size) {
3010 switch (kind) {
3011 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \
3012 case TYPE##_ELEMENTS: \
3013 *array_type = kExternal##Type##Array; \
3014 *element_size = size; \
3015 break;
3016 TYPED_ARRAYS(TYPED_ARRAY_CASE)
3017 #undef TYPED_ARRAY_CASE
3018
3019 default:
3020 UNREACHABLE();
3021 }
3022 }
3023
3024 namespace {
3025
ForFixedTypedArray(ExternalArrayType array_type,size_t * element_size,ElementsKind * element_kind)3026 static void ForFixedTypedArray(ExternalArrayType array_type,
3027 size_t* element_size,
3028 ElementsKind* element_kind) {
3029 switch (array_type) {
3030 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \
3031 case kExternal##Type##Array: \
3032 *element_size = size; \
3033 *element_kind = TYPE##_ELEMENTS; \
3034 return;
3035
3036 TYPED_ARRAYS(TYPED_ARRAY_CASE)
3037 #undef TYPED_ARRAY_CASE
3038 }
3039 UNREACHABLE();
3040 }
3041
GetTypedArrayFun(ExternalArrayType type,Isolate * isolate)3042 JSFunction* GetTypedArrayFun(ExternalArrayType type, Isolate* isolate) {
3043 Context* native_context = isolate->context()->native_context();
3044 switch (type) {
3045 #define TYPED_ARRAY_FUN(Type, type, TYPE, ctype, size) \
3046 case kExternal##Type##Array: \
3047 return native_context->type##_array_fun();
3048
3049 TYPED_ARRAYS(TYPED_ARRAY_FUN)
3050 #undef TYPED_ARRAY_FUN
3051 }
3052 UNREACHABLE();
3053 }
3054
GetTypedArrayFun(ElementsKind elements_kind,Isolate * isolate)3055 JSFunction* GetTypedArrayFun(ElementsKind elements_kind, Isolate* isolate) {
3056 Context* native_context = isolate->context()->native_context();
3057 switch (elements_kind) {
3058 #define TYPED_ARRAY_FUN(Type, type, TYPE, ctype, size) \
3059 case TYPE##_ELEMENTS: \
3060 return native_context->type##_array_fun();
3061
3062 TYPED_ARRAYS(TYPED_ARRAY_FUN)
3063 #undef TYPED_ARRAY_FUN
3064
3065 default:
3066 UNREACHABLE();
3067 }
3068 }
3069
SetupArrayBufferView(i::Isolate * isolate,i::Handle<i::JSArrayBufferView> obj,i::Handle<i::JSArrayBuffer> buffer,size_t byte_offset,size_t byte_length,PretenureFlag pretenure=NOT_TENURED)3070 void SetupArrayBufferView(i::Isolate* isolate,
3071 i::Handle<i::JSArrayBufferView> obj,
3072 i::Handle<i::JSArrayBuffer> buffer,
3073 size_t byte_offset, size_t byte_length,
3074 PretenureFlag pretenure = NOT_TENURED) {
3075 DCHECK(byte_offset + byte_length <=
3076 static_cast<size_t>(buffer->byte_length()->Number()));
3077
3078 DCHECK_EQ(obj->GetEmbedderFieldCount(),
3079 v8::ArrayBufferView::kEmbedderFieldCount);
3080 for (int i = 0; i < v8::ArrayBufferView::kEmbedderFieldCount; i++) {
3081 obj->SetEmbedderField(i, Smi::kZero);
3082 }
3083
3084 obj->set_buffer(*buffer);
3085
3086 i::Handle<i::Object> byte_offset_object =
3087 isolate->factory()->NewNumberFromSize(byte_offset, pretenure);
3088 obj->set_byte_offset(*byte_offset_object);
3089
3090 i::Handle<i::Object> byte_length_object =
3091 isolate->factory()->NewNumberFromSize(byte_length, pretenure);
3092 obj->set_byte_length(*byte_length_object);
3093 }
3094
3095 } // namespace
3096
NewJSTypedArray(ExternalArrayType type,PretenureFlag pretenure)3097 Handle<JSTypedArray> Factory::NewJSTypedArray(ExternalArrayType type,
3098 PretenureFlag pretenure) {
3099 Handle<JSFunction> typed_array_fun(GetTypedArrayFun(type, isolate()));
3100 Handle<Map> map(typed_array_fun->initial_map(), isolate());
3101 return Handle<JSTypedArray>::cast(NewJSObjectFromMap(map, pretenure));
3102 }
3103
NewJSTypedArray(ElementsKind elements_kind,PretenureFlag pretenure)3104 Handle<JSTypedArray> Factory::NewJSTypedArray(ElementsKind elements_kind,
3105 PretenureFlag pretenure) {
3106 Handle<JSFunction> typed_array_fun(GetTypedArrayFun(elements_kind, isolate()),
3107 isolate());
3108 Handle<Map> map(typed_array_fun->initial_map(), isolate());
3109 return Handle<JSTypedArray>::cast(NewJSObjectFromMap(map, pretenure));
3110 }
3111
NewJSTypedArray(ExternalArrayType type,Handle<JSArrayBuffer> buffer,size_t byte_offset,size_t length,PretenureFlag pretenure)3112 Handle<JSTypedArray> Factory::NewJSTypedArray(ExternalArrayType type,
3113 Handle<JSArrayBuffer> buffer,
3114 size_t byte_offset, size_t length,
3115 PretenureFlag pretenure) {
3116 Handle<JSTypedArray> obj = NewJSTypedArray(type, pretenure);
3117
3118 size_t element_size;
3119 ElementsKind elements_kind;
3120 ForFixedTypedArray(type, &element_size, &elements_kind);
3121
3122 CHECK_EQ(byte_offset % element_size, 0);
3123
3124 CHECK(length <= (std::numeric_limits<size_t>::max() / element_size));
3125 CHECK(length <= static_cast<size_t>(Smi::kMaxValue));
3126 size_t byte_length = length * element_size;
3127 SetupArrayBufferView(isolate(), obj, buffer, byte_offset, byte_length,
3128 pretenure);
3129
3130 Handle<Object> length_object = NewNumberFromSize(length, pretenure);
3131 obj->set_length(*length_object);
3132
3133 Handle<FixedTypedArrayBase> elements = NewFixedTypedArrayWithExternalPointer(
3134 static_cast<int>(length), type,
3135 static_cast<uint8_t*>(buffer->backing_store()) + byte_offset, pretenure);
3136 Handle<Map> map = JSObject::GetElementsTransitionMap(obj, elements_kind);
3137 JSObject::SetMapAndElements(obj, map, elements);
3138 return obj;
3139 }
3140
NewJSTypedArray(ElementsKind elements_kind,size_t number_of_elements,PretenureFlag pretenure)3141 Handle<JSTypedArray> Factory::NewJSTypedArray(ElementsKind elements_kind,
3142 size_t number_of_elements,
3143 PretenureFlag pretenure) {
3144 Handle<JSTypedArray> obj = NewJSTypedArray(elements_kind, pretenure);
3145 DCHECK_EQ(obj->GetEmbedderFieldCount(),
3146 v8::ArrayBufferView::kEmbedderFieldCount);
3147 for (int i = 0; i < v8::ArrayBufferView::kEmbedderFieldCount; i++) {
3148 obj->SetEmbedderField(i, Smi::kZero);
3149 }
3150
3151 size_t element_size;
3152 ExternalArrayType array_type;
3153 TypeAndSizeForElementsKind(elements_kind, &array_type, &element_size);
3154
3155 CHECK(number_of_elements <=
3156 (std::numeric_limits<size_t>::max() / element_size));
3157 CHECK(number_of_elements <= static_cast<size_t>(Smi::kMaxValue));
3158 size_t byte_length = number_of_elements * element_size;
3159
3160 obj->set_byte_offset(Smi::kZero);
3161 i::Handle<i::Object> byte_length_object =
3162 NewNumberFromSize(byte_length, pretenure);
3163 obj->set_byte_length(*byte_length_object);
3164 Handle<Object> length_object =
3165 NewNumberFromSize(number_of_elements, pretenure);
3166 obj->set_length(*length_object);
3167
3168 Handle<JSArrayBuffer> buffer =
3169 NewJSArrayBuffer(SharedFlag::kNotShared, pretenure);
3170 JSArrayBuffer::Setup(buffer, isolate(), true, nullptr, byte_length,
3171 SharedFlag::kNotShared);
3172 obj->set_buffer(*buffer);
3173 Handle<FixedTypedArrayBase> elements = NewFixedTypedArray(
3174 number_of_elements, byte_length, array_type, true, pretenure);
3175 obj->set_elements(*elements);
3176 return obj;
3177 }
3178
NewJSDataView(Handle<JSArrayBuffer> buffer,size_t byte_offset,size_t byte_length)3179 Handle<JSDataView> Factory::NewJSDataView(Handle<JSArrayBuffer> buffer,
3180 size_t byte_offset,
3181 size_t byte_length) {
3182 Handle<Map> map(isolate()->native_context()->data_view_fun()->initial_map(),
3183 isolate());
3184 Handle<JSDataView> obj = Handle<JSDataView>::cast(NewJSObjectFromMap(map));
3185 SetupArrayBufferView(isolate(), obj, buffer, byte_offset, byte_length);
3186 return obj;
3187 }
3188
NewJSBoundFunction(Handle<JSReceiver> target_function,Handle<Object> bound_this,Vector<Handle<Object>> bound_args)3189 MaybeHandle<JSBoundFunction> Factory::NewJSBoundFunction(
3190 Handle<JSReceiver> target_function, Handle<Object> bound_this,
3191 Vector<Handle<Object>> bound_args) {
3192 DCHECK(target_function->IsCallable());
3193 STATIC_ASSERT(Code::kMaxArguments <= FixedArray::kMaxLength);
3194 if (bound_args.length() >= Code::kMaxArguments) {
3195 THROW_NEW_ERROR(isolate(),
3196 NewRangeError(MessageTemplate::kTooManyArguments),
3197 JSBoundFunction);
3198 }
3199
3200 // Determine the prototype of the {target_function}.
3201 Handle<Object> prototype;
3202 ASSIGN_RETURN_ON_EXCEPTION(
3203 isolate(), prototype,
3204 JSReceiver::GetPrototype(isolate(), target_function), JSBoundFunction);
3205
3206 SaveContext save(isolate());
3207 isolate()->set_context(*target_function->GetCreationContext());
3208
3209 // Create the [[BoundArguments]] for the result.
3210 Handle<FixedArray> bound_arguments;
3211 if (bound_args.length() == 0) {
3212 bound_arguments = empty_fixed_array();
3213 } else {
3214 bound_arguments = NewFixedArray(bound_args.length());
3215 for (int i = 0; i < bound_args.length(); ++i) {
3216 bound_arguments->set(i, *bound_args[i]);
3217 }
3218 }
3219
3220 // Setup the map for the JSBoundFunction instance.
3221 Handle<Map> map = target_function->IsConstructor()
3222 ? isolate()->bound_function_with_constructor_map()
3223 : isolate()->bound_function_without_constructor_map();
3224 if (map->prototype() != *prototype) {
3225 map = Map::TransitionToPrototype(map, prototype);
3226 }
3227 DCHECK_EQ(target_function->IsConstructor(), map->is_constructor());
3228
3229 // Setup the JSBoundFunction instance.
3230 Handle<JSBoundFunction> result =
3231 Handle<JSBoundFunction>::cast(NewJSObjectFromMap(map));
3232 result->set_bound_target_function(*target_function);
3233 result->set_bound_this(*bound_this);
3234 result->set_bound_arguments(*bound_arguments);
3235 return result;
3236 }
3237
3238 // ES6 section 9.5.15 ProxyCreate (target, handler)
NewJSProxy(Handle<JSReceiver> target,Handle<JSReceiver> handler)3239 Handle<JSProxy> Factory::NewJSProxy(Handle<JSReceiver> target,
3240 Handle<JSReceiver> handler) {
3241 // Allocate the proxy object.
3242 Handle<Map> map;
3243 if (target->IsCallable()) {
3244 if (target->IsConstructor()) {
3245 map = Handle<Map>(isolate()->proxy_constructor_map());
3246 } else {
3247 map = Handle<Map>(isolate()->proxy_callable_map());
3248 }
3249 } else {
3250 map = Handle<Map>(isolate()->proxy_map());
3251 }
3252 DCHECK(map->prototype()->IsNull(isolate()));
3253 Handle<JSProxy> result(JSProxy::cast(New(map, NOT_TENURED)), isolate());
3254 result->initialize_properties();
3255 result->set_target(*target);
3256 result->set_handler(*handler);
3257 return result;
3258 }
3259
NewUninitializedJSGlobalProxy(int size)3260 Handle<JSGlobalProxy> Factory::NewUninitializedJSGlobalProxy(int size) {
3261 // Create an empty shell of a JSGlobalProxy that needs to be reinitialized
3262 // via ReinitializeJSGlobalProxy later.
3263 Handle<Map> map = NewMap(JS_GLOBAL_PROXY_TYPE, size);
3264 // Maintain invariant expected from any JSGlobalProxy.
3265 map->set_is_access_check_needed(true);
3266 map->set_may_have_interesting_symbols(true);
3267 return Handle<JSGlobalProxy>::cast(NewJSObjectFromMap(map, NOT_TENURED));
3268 }
3269
ReinitializeJSGlobalProxy(Handle<JSGlobalProxy> object,Handle<JSFunction> constructor)3270 void Factory::ReinitializeJSGlobalProxy(Handle<JSGlobalProxy> object,
3271 Handle<JSFunction> constructor) {
3272 DCHECK(constructor->has_initial_map());
3273 Handle<Map> map(constructor->initial_map(), isolate());
3274 Handle<Map> old_map(object->map(), isolate());
3275
3276 // The proxy's hash should be retained across reinitialization.
3277 Handle<Object> raw_properties_or_hash(object->raw_properties_or_hash(),
3278 isolate());
3279
3280 if (old_map->is_prototype_map()) {
3281 map = Map::Copy(map, "CopyAsPrototypeForJSGlobalProxy");
3282 map->set_is_prototype_map(true);
3283 }
3284 JSObject::NotifyMapChange(old_map, map, isolate());
3285 old_map->NotifyLeafMapLayoutChange();
3286
3287 // Check that the already allocated object has the same size and type as
3288 // objects allocated using the constructor.
3289 DCHECK(map->instance_size() == old_map->instance_size());
3290 DCHECK(map->instance_type() == old_map->instance_type());
3291
3292 // In order to keep heap in consistent state there must be no allocations
3293 // before object re-initialization is finished.
3294 DisallowHeapAllocation no_allocation;
3295
3296 // Reset the map for the object.
3297 object->synchronized_set_map(*map);
3298
3299 // Reinitialize the object from the constructor map.
3300 InitializeJSObjectFromMap(object, raw_properties_or_hash, map);
3301 }
3302
NewSharedFunctionInfoForLiteral(FunctionLiteral * literal,Handle<Script> script,bool is_toplevel)3303 Handle<SharedFunctionInfo> Factory::NewSharedFunctionInfoForLiteral(
3304 FunctionLiteral* literal, Handle<Script> script, bool is_toplevel) {
3305 FunctionKind kind = literal->kind();
3306 Handle<SharedFunctionInfo> shared = NewSharedFunctionInfoForBuiltin(
3307 literal->name(), Builtins::kCompileLazy, kind);
3308 SharedFunctionInfo::InitFromFunctionLiteral(shared, literal, is_toplevel);
3309 SharedFunctionInfo::SetScript(shared, script, false);
3310 return shared;
3311 }
3312
NewJSMessageObject(MessageTemplate::Template message,Handle<Object> argument,int start_position,int end_position,Handle<Object> script,Handle<Object> stack_frames)3313 Handle<JSMessageObject> Factory::NewJSMessageObject(
3314 MessageTemplate::Template message, Handle<Object> argument,
3315 int start_position, int end_position, Handle<Object> script,
3316 Handle<Object> stack_frames) {
3317 Handle<Map> map = message_object_map();
3318 Handle<JSMessageObject> message_obj(
3319 JSMessageObject::cast(New(map, NOT_TENURED)), isolate());
3320 message_obj->set_raw_properties_or_hash(*empty_fixed_array(),
3321 SKIP_WRITE_BARRIER);
3322 message_obj->initialize_elements();
3323 message_obj->set_elements(*empty_fixed_array(), SKIP_WRITE_BARRIER);
3324 message_obj->set_type(message);
3325 message_obj->set_argument(*argument);
3326 message_obj->set_start_position(start_position);
3327 message_obj->set_end_position(end_position);
3328 message_obj->set_script(*script);
3329 message_obj->set_stack_frames(*stack_frames);
3330 message_obj->set_error_level(v8::Isolate::kMessageError);
3331 return message_obj;
3332 }
3333
NewSharedFunctionInfoForApiFunction(MaybeHandle<String> maybe_name,Handle<FunctionTemplateInfo> function_template_info,FunctionKind kind)3334 Handle<SharedFunctionInfo> Factory::NewSharedFunctionInfoForApiFunction(
3335 MaybeHandle<String> maybe_name,
3336 Handle<FunctionTemplateInfo> function_template_info, FunctionKind kind) {
3337 Handle<SharedFunctionInfo> shared = NewSharedFunctionInfo(
3338 maybe_name, function_template_info, Builtins::kNoBuiltinId, kind);
3339 return shared;
3340 }
3341
NewSharedFunctionInfoForBuiltin(MaybeHandle<String> maybe_name,int builtin_index,FunctionKind kind)3342 Handle<SharedFunctionInfo> Factory::NewSharedFunctionInfoForBuiltin(
3343 MaybeHandle<String> maybe_name, int builtin_index, FunctionKind kind) {
3344 Handle<SharedFunctionInfo> shared = NewSharedFunctionInfo(
3345 maybe_name, MaybeHandle<Code>(), builtin_index, kind);
3346 return shared;
3347 }
3348
NewSharedFunctionInfo(MaybeHandle<String> maybe_name,MaybeHandle<HeapObject> maybe_function_data,int maybe_builtin_index,FunctionKind kind)3349 Handle<SharedFunctionInfo> Factory::NewSharedFunctionInfo(
3350 MaybeHandle<String> maybe_name, MaybeHandle<HeapObject> maybe_function_data,
3351 int maybe_builtin_index, FunctionKind kind) {
3352 // Function names are assumed to be flat elsewhere. Must flatten before
3353 // allocating SharedFunctionInfo to avoid GC seeing the uninitialized SFI.
3354 Handle<String> shared_name;
3355 bool has_shared_name = maybe_name.ToHandle(&shared_name);
3356 if (has_shared_name) {
3357 shared_name = String::Flatten(shared_name, TENURED);
3358 }
3359
3360 Handle<Map> map = shared_function_info_map();
3361 Handle<SharedFunctionInfo> share(SharedFunctionInfo::cast(New(map, TENURED)),
3362 isolate());
3363 {
3364 DisallowHeapAllocation no_allocation;
3365
3366 // Set pointer fields.
3367 share->set_name_or_scope_info(
3368 has_shared_name ? *shared_name
3369 : SharedFunctionInfo::kNoSharedNameSentinel);
3370 Handle<HeapObject> function_data;
3371 if (maybe_function_data.ToHandle(&function_data)) {
3372 // If we pass function_data then we shouldn't pass a builtin index, and
3373 // the function_data should not be code with a builtin.
3374 DCHECK(!Builtins::IsBuiltinId(maybe_builtin_index));
3375 DCHECK_IMPLIES(function_data->IsCode(),
3376 !Code::cast(*function_data)->is_builtin());
3377 share->set_function_data(*function_data);
3378 } else if (Builtins::IsBuiltinId(maybe_builtin_index)) {
3379 DCHECK_NE(maybe_builtin_index, Builtins::kDeserializeLazy);
3380 share->set_builtin_id(maybe_builtin_index);
3381 } else {
3382 share->set_builtin_id(Builtins::kIllegal);
3383 }
3384 // Generally functions won't have feedback, unless they have been created
3385 // from a FunctionLiteral. Those can just reset this field to keep the
3386 // SharedFunctionInfo in a consistent state.
3387 if (maybe_builtin_index == Builtins::kCompileLazy) {
3388 share->set_raw_outer_scope_info_or_feedback_metadata(*the_hole_value(),
3389 SKIP_WRITE_BARRIER);
3390 } else {
3391 share->set_raw_outer_scope_info_or_feedback_metadata(
3392 *empty_feedback_metadata(), SKIP_WRITE_BARRIER);
3393 }
3394 share->set_script(*undefined_value(), SKIP_WRITE_BARRIER);
3395 share->set_debug_info(Smi::kZero, SKIP_WRITE_BARRIER);
3396 share->set_function_identifier(*undefined_value(), SKIP_WRITE_BARRIER);
3397 share->set_function_literal_id(FunctionLiteral::kIdTypeInvalid);
3398 #if V8_SFI_HAS_UNIQUE_ID
3399 share->set_unique_id(isolate()->GetNextUniqueSharedFunctionInfoId());
3400 #endif
3401
3402 // Set integer fields (smi or int, depending on the architecture).
3403 share->set_length(0);
3404 share->set_internal_formal_parameter_count(0);
3405 share->set_expected_nof_properties(0);
3406 share->set_raw_start_position_and_type(0);
3407 share->set_raw_end_position(0);
3408 share->set_function_token_position(0);
3409 // All flags default to false or 0.
3410 share->set_flags(0);
3411 share->CalculateConstructAsBuiltin();
3412 share->set_kind(kind);
3413
3414 share->clear_padding();
3415 }
3416 // Link into the list.
3417 Handle<Object> new_noscript_list =
3418 FixedArrayOfWeakCells::Add(noscript_shared_function_infos(), share);
3419 isolate()->heap()->set_noscript_shared_function_infos(*new_noscript_list);
3420
3421 DCHECK_EQ(SharedFunctionInfo::kNoDebuggingId, share->debugging_id());
3422 #ifdef VERIFY_HEAP
3423 share->SharedFunctionInfoVerify();
3424 #endif
3425 return share;
3426 }
3427
NumberCacheHash(Handle<FixedArray> cache,Handle<Object> number)3428 static inline int NumberCacheHash(Handle<FixedArray> cache,
3429 Handle<Object> number) {
3430 int mask = (cache->length() >> 1) - 1;
3431 if (number->IsSmi()) {
3432 return Handle<Smi>::cast(number)->value() & mask;
3433 } else {
3434 int64_t bits = bit_cast<int64_t>(number->Number());
3435 return (static_cast<int>(bits) ^ static_cast<int>(bits >> 32)) & mask;
3436 }
3437 }
3438
GetNumberStringCache(Handle<Object> number)3439 Handle<Object> Factory::GetNumberStringCache(Handle<Object> number) {
3440 DisallowHeapAllocation no_gc;
3441 int hash = NumberCacheHash(number_string_cache(), number);
3442 Object* key = number_string_cache()->get(hash * 2);
3443 if (key == *number || (key->IsHeapNumber() && number->IsHeapNumber() &&
3444 key->Number() == number->Number())) {
3445 return Handle<String>(
3446 String::cast(number_string_cache()->get(hash * 2 + 1)), isolate());
3447 }
3448 return undefined_value();
3449 }
3450
SetNumberStringCache(Handle<Object> number,Handle<String> string)3451 void Factory::SetNumberStringCache(Handle<Object> number,
3452 Handle<String> string) {
3453 int hash = NumberCacheHash(number_string_cache(), number);
3454 if (number_string_cache()->get(hash * 2) != *undefined_value()) {
3455 int full_size = isolate()->heap()->FullSizeNumberStringCacheLength();
3456 if (number_string_cache()->length() != full_size) {
3457 Handle<FixedArray> new_cache = NewFixedArray(full_size, TENURED);
3458 isolate()->heap()->set_number_string_cache(*new_cache);
3459 return;
3460 }
3461 }
3462 number_string_cache()->set(hash * 2, *number);
3463 number_string_cache()->set(hash * 2 + 1, *string);
3464 }
3465
NumberToString(Handle<Object> number,bool check_number_string_cache)3466 Handle<String> Factory::NumberToString(Handle<Object> number,
3467 bool check_number_string_cache) {
3468 isolate()->counters()->number_to_string_runtime()->Increment();
3469 if (check_number_string_cache) {
3470 Handle<Object> cached = GetNumberStringCache(number);
3471 if (!cached->IsUndefined(isolate())) return Handle<String>::cast(cached);
3472 }
3473
3474 char arr[100];
3475 Vector<char> buffer(arr, arraysize(arr));
3476 const char* str;
3477 if (number->IsSmi()) {
3478 int num = Handle<Smi>::cast(number)->value();
3479 str = IntToCString(num, buffer);
3480 } else {
3481 double num = Handle<HeapNumber>::cast(number)->value();
3482 str = DoubleToCString(num, buffer);
3483 }
3484
3485 // We tenure the allocated string since it is referenced from the
3486 // number-string cache which lives in the old space.
3487 Handle<String> js_string = NewStringFromAsciiChecked(str, TENURED);
3488 SetNumberStringCache(number, js_string);
3489 return js_string;
3490 }
3491
NewDebugInfo(Handle<SharedFunctionInfo> shared)3492 Handle<DebugInfo> Factory::NewDebugInfo(Handle<SharedFunctionInfo> shared) {
3493 DCHECK(!shared->HasDebugInfo());
3494 Heap* heap = isolate()->heap();
3495
3496 Handle<DebugInfo> debug_info =
3497 Handle<DebugInfo>::cast(NewStruct(DEBUG_INFO_TYPE, TENURED));
3498 debug_info->set_flags(DebugInfo::kNone);
3499 debug_info->set_shared(*shared);
3500 debug_info->set_debugger_hints(shared->debugger_hints());
3501 debug_info->set_debug_bytecode_array(heap->undefined_value());
3502 debug_info->set_break_points(heap->empty_fixed_array());
3503
3504 // Link debug info to function.
3505 shared->set_debug_info(*debug_info);
3506
3507 return debug_info;
3508 }
3509
NewCoverageInfo(const ZoneVector<SourceRange> & slots)3510 Handle<CoverageInfo> Factory::NewCoverageInfo(
3511 const ZoneVector<SourceRange>& slots) {
3512 const int slot_count = static_cast<int>(slots.size());
3513
3514 const int length = CoverageInfo::FixedArrayLengthForSlotCount(slot_count);
3515 Handle<CoverageInfo> info =
3516 Handle<CoverageInfo>::cast(NewUninitializedFixedArray(length));
3517
3518 for (int i = 0; i < slot_count; i++) {
3519 SourceRange range = slots[i];
3520 info->InitializeSlot(i, range.start, range.end);
3521 }
3522
3523 return info;
3524 }
3525
NewBreakPointInfo(int source_position)3526 Handle<BreakPointInfo> Factory::NewBreakPointInfo(int source_position) {
3527 Handle<BreakPointInfo> new_break_point_info =
3528 Handle<BreakPointInfo>::cast(NewStruct(TUPLE2_TYPE, TENURED));
3529 new_break_point_info->set_source_position(source_position);
3530 new_break_point_info->set_break_points(*undefined_value());
3531 return new_break_point_info;
3532 }
3533
NewBreakPoint(int id,Handle<String> condition)3534 Handle<BreakPoint> Factory::NewBreakPoint(int id, Handle<String> condition) {
3535 Handle<BreakPoint> new_break_point =
3536 Handle<BreakPoint>::cast(NewStruct(TUPLE2_TYPE, TENURED));
3537 new_break_point->set_id(id);
3538 new_break_point->set_condition(*condition);
3539 return new_break_point;
3540 }
3541
NewStackFrameInfo()3542 Handle<StackFrameInfo> Factory::NewStackFrameInfo() {
3543 Handle<StackFrameInfo> stack_frame_info = Handle<StackFrameInfo>::cast(
3544 NewStruct(STACK_FRAME_INFO_TYPE, NOT_TENURED));
3545 stack_frame_info->set_line_number(0);
3546 stack_frame_info->set_column_number(0);
3547 stack_frame_info->set_script_id(0);
3548 stack_frame_info->set_script_name(Smi::kZero);
3549 stack_frame_info->set_script_name_or_source_url(Smi::kZero);
3550 stack_frame_info->set_function_name(Smi::kZero);
3551 stack_frame_info->set_flag(0);
3552 return stack_frame_info;
3553 }
3554
3555 Handle<SourcePositionTableWithFrameCache>
NewSourcePositionTableWithFrameCache(Handle<ByteArray> source_position_table,Handle<SimpleNumberDictionary> stack_frame_cache)3556 Factory::NewSourcePositionTableWithFrameCache(
3557 Handle<ByteArray> source_position_table,
3558 Handle<SimpleNumberDictionary> stack_frame_cache) {
3559 Handle<SourcePositionTableWithFrameCache>
3560 source_position_table_with_frame_cache =
3561 Handle<SourcePositionTableWithFrameCache>::cast(
3562 NewStruct(TUPLE2_TYPE, TENURED));
3563 source_position_table_with_frame_cache->set_source_position_table(
3564 *source_position_table);
3565 source_position_table_with_frame_cache->set_stack_frame_cache(
3566 *stack_frame_cache);
3567 return source_position_table_with_frame_cache;
3568 }
3569
NewArgumentsObject(Handle<JSFunction> callee,int length)3570 Handle<JSObject> Factory::NewArgumentsObject(Handle<JSFunction> callee,
3571 int length) {
3572 bool strict_mode_callee = is_strict(callee->shared()->language_mode()) ||
3573 !callee->shared()->has_simple_parameters();
3574 Handle<Map> map = strict_mode_callee ? isolate()->strict_arguments_map()
3575 : isolate()->sloppy_arguments_map();
3576 AllocationSiteUsageContext context(isolate(), Handle<AllocationSite>(),
3577 false);
3578 DCHECK(!isolate()->has_pending_exception());
3579 Handle<JSObject> result = NewJSObjectFromMap(map);
3580 Handle<Smi> value(Smi::FromInt(length), isolate());
3581 Object::SetProperty(result, length_string(), value, LanguageMode::kStrict)
3582 .Assert();
3583 if (!strict_mode_callee) {
3584 Object::SetProperty(result, callee_string(), callee, LanguageMode::kStrict)
3585 .Assert();
3586 }
3587 return result;
3588 }
3589
ObjectLiteralMapFromCache(Handle<Context> native_context,int number_of_properties)3590 Handle<Map> Factory::ObjectLiteralMapFromCache(Handle<Context> native_context,
3591 int number_of_properties) {
3592 DCHECK(native_context->IsNativeContext());
3593 const int kMapCacheSize = 128;
3594 // We do not cache maps for too many properties or when running builtin code.
3595 if (isolate()->bootstrapper()->IsActive()) {
3596 return Map::Create(isolate(), number_of_properties);
3597 }
3598 // Use initial slow object proto map for too many properties.
3599 if (number_of_properties > kMapCacheSize) {
3600 return handle(native_context->slow_object_with_object_prototype_map(),
3601 isolate());
3602 }
3603 if (number_of_properties == 0) {
3604 // Reuse the initial map of the Object function if the literal has no
3605 // predeclared properties.
3606 return handle(native_context->object_function()->initial_map(), isolate());
3607 }
3608
3609 int cache_index = number_of_properties - 1;
3610 Handle<Object> maybe_cache(native_context->map_cache(), isolate());
3611 if (maybe_cache->IsUndefined(isolate())) {
3612 // Allocate the new map cache for the native context.
3613 maybe_cache = NewFixedArray(kMapCacheSize, TENURED);
3614 native_context->set_map_cache(*maybe_cache);
3615 } else {
3616 // Check to see whether there is a matching element in the cache.
3617 Handle<FixedArray> cache = Handle<FixedArray>::cast(maybe_cache);
3618 Object* result = cache->get(cache_index);
3619 if (result->IsWeakCell()) {
3620 WeakCell* cell = WeakCell::cast(result);
3621 if (!cell->cleared()) {
3622 Map* map = Map::cast(cell->value());
3623 DCHECK(!map->is_dictionary_map());
3624 return handle(map, isolate());
3625 }
3626 }
3627 }
3628 // Create a new map and add it to the cache.
3629 Handle<FixedArray> cache = Handle<FixedArray>::cast(maybe_cache);
3630 Handle<Map> map = Map::Create(isolate(), number_of_properties);
3631 DCHECK(!map->is_dictionary_map());
3632 Handle<WeakCell> cell = NewWeakCell(map);
3633 cache->set(cache_index, *cell);
3634 return map;
3635 }
3636
NewLoadHandler(int data_count)3637 Handle<LoadHandler> Factory::NewLoadHandler(int data_count) {
3638 Handle<Map> map;
3639 switch (data_count) {
3640 case 1:
3641 map = load_handler1_map();
3642 break;
3643 case 2:
3644 map = load_handler2_map();
3645 break;
3646 case 3:
3647 map = load_handler3_map();
3648 break;
3649 default:
3650 UNREACHABLE();
3651 break;
3652 }
3653 return handle(LoadHandler::cast(New(map, TENURED)), isolate());
3654 }
3655
NewStoreHandler(int data_count)3656 Handle<StoreHandler> Factory::NewStoreHandler(int data_count) {
3657 Handle<Map> map;
3658 switch (data_count) {
3659 case 0:
3660 map = store_handler0_map();
3661 break;
3662 case 1:
3663 map = store_handler1_map();
3664 break;
3665 case 2:
3666 map = store_handler2_map();
3667 break;
3668 case 3:
3669 map = store_handler3_map();
3670 break;
3671 default:
3672 UNREACHABLE();
3673 break;
3674 }
3675 return handle(StoreHandler::cast(New(map, TENURED)), isolate());
3676 }
3677
SetRegExpAtomData(Handle<JSRegExp> regexp,JSRegExp::Type type,Handle<String> source,JSRegExp::Flags flags,Handle<Object> data)3678 void Factory::SetRegExpAtomData(Handle<JSRegExp> regexp, JSRegExp::Type type,
3679 Handle<String> source, JSRegExp::Flags flags,
3680 Handle<Object> data) {
3681 Handle<FixedArray> store = NewFixedArray(JSRegExp::kAtomDataSize);
3682
3683 store->set(JSRegExp::kTagIndex, Smi::FromInt(type));
3684 store->set(JSRegExp::kSourceIndex, *source);
3685 store->set(JSRegExp::kFlagsIndex, Smi::FromInt(flags));
3686 store->set(JSRegExp::kAtomPatternIndex, *data);
3687 regexp->set_data(*store);
3688 }
3689
SetRegExpIrregexpData(Handle<JSRegExp> regexp,JSRegExp::Type type,Handle<String> source,JSRegExp::Flags flags,int capture_count)3690 void Factory::SetRegExpIrregexpData(Handle<JSRegExp> regexp,
3691 JSRegExp::Type type, Handle<String> source,
3692 JSRegExp::Flags flags, int capture_count) {
3693 Handle<FixedArray> store = NewFixedArray(JSRegExp::kIrregexpDataSize);
3694 Smi* uninitialized = Smi::FromInt(JSRegExp::kUninitializedValue);
3695 store->set(JSRegExp::kTagIndex, Smi::FromInt(type));
3696 store->set(JSRegExp::kSourceIndex, *source);
3697 store->set(JSRegExp::kFlagsIndex, Smi::FromInt(flags));
3698 store->set(JSRegExp::kIrregexpLatin1CodeIndex, uninitialized);
3699 store->set(JSRegExp::kIrregexpUC16CodeIndex, uninitialized);
3700 store->set(JSRegExp::kIrregexpMaxRegisterCountIndex, Smi::kZero);
3701 store->set(JSRegExp::kIrregexpCaptureCountIndex, Smi::FromInt(capture_count));
3702 store->set(JSRegExp::kIrregexpCaptureNameMapIndex, uninitialized);
3703 regexp->set_data(*store);
3704 }
3705
NewRegExpMatchInfo()3706 Handle<RegExpMatchInfo> Factory::NewRegExpMatchInfo() {
3707 // Initially, the last match info consists of all fixed fields plus space for
3708 // the match itself (i.e., 2 capture indices).
3709 static const int kInitialSize = RegExpMatchInfo::kFirstCaptureIndex +
3710 RegExpMatchInfo::kInitialCaptureIndices;
3711
3712 Handle<FixedArray> elems = NewFixedArray(kInitialSize);
3713 Handle<RegExpMatchInfo> result = Handle<RegExpMatchInfo>::cast(elems);
3714
3715 result->SetNumberOfCaptureRegisters(RegExpMatchInfo::kInitialCaptureIndices);
3716 result->SetLastSubject(*empty_string());
3717 result->SetLastInput(*undefined_value());
3718 result->SetCapture(0, 0);
3719 result->SetCapture(1, 0);
3720
3721 return result;
3722 }
3723
GlobalConstantFor(Handle<Name> name)3724 Handle<Object> Factory::GlobalConstantFor(Handle<Name> name) {
3725 if (Name::Equals(name, undefined_string())) return undefined_value();
3726 if (Name::Equals(name, NaN_string())) return nan_value();
3727 if (Name::Equals(name, Infinity_string())) return infinity_value();
3728 return Handle<Object>::null();
3729 }
3730
ToBoolean(bool value)3731 Handle<Object> Factory::ToBoolean(bool value) {
3732 return value ? true_value() : false_value();
3733 }
3734
ToPrimitiveHintString(ToPrimitiveHint hint)3735 Handle<String> Factory::ToPrimitiveHintString(ToPrimitiveHint hint) {
3736 switch (hint) {
3737 case ToPrimitiveHint::kDefault:
3738 return default_string();
3739 case ToPrimitiveHint::kNumber:
3740 return number_string();
3741 case ToPrimitiveHint::kString:
3742 return string_string();
3743 }
3744 UNREACHABLE();
3745 }
3746
CreateSloppyFunctionMap(FunctionMode function_mode,MaybeHandle<JSFunction> maybe_empty_function)3747 Handle<Map> Factory::CreateSloppyFunctionMap(
3748 FunctionMode function_mode, MaybeHandle<JSFunction> maybe_empty_function) {
3749 bool has_prototype = IsFunctionModeWithPrototype(function_mode);
3750 int header_size = has_prototype ? JSFunction::kSizeWithPrototype
3751 : JSFunction::kSizeWithoutPrototype;
3752 int descriptors_count = has_prototype ? 5 : 4;
3753 int inobject_properties_count = 0;
3754 if (IsFunctionModeWithName(function_mode)) ++inobject_properties_count;
3755
3756 Handle<Map> map = NewMap(
3757 JS_FUNCTION_TYPE, header_size + inobject_properties_count * kPointerSize,
3758 TERMINAL_FAST_ELEMENTS_KIND, inobject_properties_count);
3759 map->set_has_prototype_slot(has_prototype);
3760 map->set_is_constructor(has_prototype);
3761 map->set_is_callable(true);
3762 Handle<JSFunction> empty_function;
3763 if (maybe_empty_function.ToHandle(&empty_function)) {
3764 Map::SetPrototype(map, empty_function);
3765 }
3766
3767 //
3768 // Setup descriptors array.
3769 //
3770 Map::EnsureDescriptorSlack(map, descriptors_count);
3771
3772 PropertyAttributes ro_attribs =
3773 static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE | READ_ONLY);
3774 PropertyAttributes rw_attribs =
3775 static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE);
3776 PropertyAttributes roc_attribs =
3777 static_cast<PropertyAttributes>(DONT_ENUM | READ_ONLY);
3778
3779 int field_index = 0;
3780 STATIC_ASSERT(JSFunction::kLengthDescriptorIndex == 0);
3781 { // Add length accessor.
3782 Descriptor d = Descriptor::AccessorConstant(
3783 length_string(), function_length_accessor(), roc_attribs);
3784 map->AppendDescriptor(&d);
3785 }
3786
3787 STATIC_ASSERT(JSFunction::kNameDescriptorIndex == 1);
3788 if (IsFunctionModeWithName(function_mode)) {
3789 // Add name field.
3790 Handle<Name> name = isolate()->factory()->name_string();
3791 Descriptor d = Descriptor::DataField(name, field_index++, roc_attribs,
3792 Representation::Tagged());
3793 map->AppendDescriptor(&d);
3794
3795 } else {
3796 // Add name accessor.
3797 Descriptor d = Descriptor::AccessorConstant(
3798 name_string(), function_name_accessor(), roc_attribs);
3799 map->AppendDescriptor(&d);
3800 }
3801 { // Add arguments accessor.
3802 Descriptor d = Descriptor::AccessorConstant(
3803 arguments_string(), function_arguments_accessor(), ro_attribs);
3804 map->AppendDescriptor(&d);
3805 }
3806 { // Add caller accessor.
3807 Descriptor d = Descriptor::AccessorConstant(
3808 caller_string(), function_caller_accessor(), ro_attribs);
3809 map->AppendDescriptor(&d);
3810 }
3811 if (IsFunctionModeWithPrototype(function_mode)) {
3812 // Add prototype accessor.
3813 PropertyAttributes attribs =
3814 IsFunctionModeWithWritablePrototype(function_mode) ? rw_attribs
3815 : ro_attribs;
3816 Descriptor d = Descriptor::AccessorConstant(
3817 prototype_string(), function_prototype_accessor(), attribs);
3818 map->AppendDescriptor(&d);
3819 }
3820 DCHECK_EQ(inobject_properties_count, field_index);
3821 return map;
3822 }
3823
CreateStrictFunctionMap(FunctionMode function_mode,Handle<JSFunction> empty_function)3824 Handle<Map> Factory::CreateStrictFunctionMap(
3825 FunctionMode function_mode, Handle<JSFunction> empty_function) {
3826 bool has_prototype = IsFunctionModeWithPrototype(function_mode);
3827 int header_size = has_prototype ? JSFunction::kSizeWithPrototype
3828 : JSFunction::kSizeWithoutPrototype;
3829 int inobject_properties_count = 0;
3830 if (IsFunctionModeWithName(function_mode)) ++inobject_properties_count;
3831 if (IsFunctionModeWithHomeObject(function_mode)) ++inobject_properties_count;
3832 int descriptors_count = (IsFunctionModeWithPrototype(function_mode) ? 3 : 2) +
3833 inobject_properties_count;
3834
3835 Handle<Map> map = NewMap(
3836 JS_FUNCTION_TYPE, header_size + inobject_properties_count * kPointerSize,
3837 TERMINAL_FAST_ELEMENTS_KIND, inobject_properties_count);
3838 map->set_has_prototype_slot(has_prototype);
3839 map->set_is_constructor(has_prototype);
3840 map->set_is_callable(true);
3841 Map::SetPrototype(map, empty_function);
3842
3843 //
3844 // Setup descriptors array.
3845 //
3846 Map::EnsureDescriptorSlack(map, descriptors_count);
3847
3848 PropertyAttributes rw_attribs =
3849 static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE);
3850 PropertyAttributes ro_attribs =
3851 static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE | READ_ONLY);
3852 PropertyAttributes roc_attribs =
3853 static_cast<PropertyAttributes>(DONT_ENUM | READ_ONLY);
3854
3855 int field_index = 0;
3856 STATIC_ASSERT(JSFunction::kLengthDescriptorIndex == 0);
3857 { // Add length accessor.
3858 Descriptor d = Descriptor::AccessorConstant(
3859 length_string(), function_length_accessor(), roc_attribs);
3860 map->AppendDescriptor(&d);
3861 }
3862
3863 STATIC_ASSERT(JSFunction::kNameDescriptorIndex == 1);
3864 if (IsFunctionModeWithName(function_mode)) {
3865 // Add name field.
3866 Handle<Name> name = isolate()->factory()->name_string();
3867 Descriptor d = Descriptor::DataField(name, field_index++, roc_attribs,
3868 Representation::Tagged());
3869 map->AppendDescriptor(&d);
3870
3871 } else {
3872 // Add name accessor.
3873 Descriptor d = Descriptor::AccessorConstant(
3874 name_string(), function_name_accessor(), roc_attribs);
3875 map->AppendDescriptor(&d);
3876 }
3877
3878 STATIC_ASSERT(JSFunction::kMaybeHomeObjectDescriptorIndex == 2);
3879 if (IsFunctionModeWithHomeObject(function_mode)) {
3880 // Add home object field.
3881 Handle<Name> name = isolate()->factory()->home_object_symbol();
3882 Descriptor d = Descriptor::DataField(name, field_index++, DONT_ENUM,
3883 Representation::Tagged());
3884 map->AppendDescriptor(&d);
3885 }
3886
3887 if (IsFunctionModeWithPrototype(function_mode)) {
3888 // Add prototype accessor.
3889 PropertyAttributes attribs =
3890 IsFunctionModeWithWritablePrototype(function_mode) ? rw_attribs
3891 : ro_attribs;
3892 Descriptor d = Descriptor::AccessorConstant(
3893 prototype_string(), function_prototype_accessor(), attribs);
3894 map->AppendDescriptor(&d);
3895 }
3896 DCHECK_EQ(inobject_properties_count, field_index);
3897 return map;
3898 }
3899
CreateClassFunctionMap(Handle<JSFunction> empty_function)3900 Handle<Map> Factory::CreateClassFunctionMap(Handle<JSFunction> empty_function) {
3901 Handle<Map> map = NewMap(JS_FUNCTION_TYPE, JSFunction::kSizeWithPrototype);
3902 map->set_has_prototype_slot(true);
3903 map->set_is_constructor(true);
3904 map->set_is_prototype_map(true);
3905 map->set_is_callable(true);
3906 Map::SetPrototype(map, empty_function);
3907
3908 //
3909 // Setup descriptors array.
3910 //
3911 Map::EnsureDescriptorSlack(map, 2);
3912
3913 PropertyAttributes ro_attribs =
3914 static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE | READ_ONLY);
3915 PropertyAttributes roc_attribs =
3916 static_cast<PropertyAttributes>(DONT_ENUM | READ_ONLY);
3917
3918 STATIC_ASSERT(JSFunction::kLengthDescriptorIndex == 0);
3919 { // Add length accessor.
3920 Descriptor d = Descriptor::AccessorConstant(
3921 length_string(), function_length_accessor(), roc_attribs);
3922 map->AppendDescriptor(&d);
3923 }
3924
3925 {
3926 // Add prototype accessor.
3927 Descriptor d = Descriptor::AccessorConstant(
3928 prototype_string(), function_prototype_accessor(), ro_attribs);
3929 map->AppendDescriptor(&d);
3930 }
3931 return map;
3932 }
3933
NewJSPromiseWithoutHook(PretenureFlag pretenure)3934 Handle<JSPromise> Factory::NewJSPromiseWithoutHook(PretenureFlag pretenure) {
3935 Handle<JSPromise> promise = Handle<JSPromise>::cast(
3936 NewJSObject(isolate()->promise_function(), pretenure));
3937 promise->set_reactions_or_result(Smi::kZero);
3938 promise->set_flags(0);
3939 for (int i = 0; i < v8::Promise::kEmbedderFieldCount; i++) {
3940 promise->SetEmbedderField(i, Smi::kZero);
3941 }
3942 return promise;
3943 }
3944
NewJSPromise(PretenureFlag pretenure)3945 Handle<JSPromise> Factory::NewJSPromise(PretenureFlag pretenure) {
3946 Handle<JSPromise> promise = NewJSPromiseWithoutHook(pretenure);
3947 isolate()->RunPromiseHook(PromiseHookType::kInit, promise, undefined_value());
3948 return promise;
3949 }
3950
NewCallHandlerInfo(bool has_no_side_effect)3951 Handle<CallHandlerInfo> Factory::NewCallHandlerInfo(bool has_no_side_effect) {
3952 Handle<Map> map = has_no_side_effect
3953 ? side_effect_free_call_handler_info_map()
3954 : side_effect_call_handler_info_map();
3955 Handle<CallHandlerInfo> info(CallHandlerInfo::cast(New(map, TENURED)),
3956 isolate());
3957 Object* undefined_value = isolate()->heap()->undefined_value();
3958 info->set_callback(undefined_value);
3959 info->set_js_callback(undefined_value);
3960 info->set_data(undefined_value);
3961 return info;
3962 }
3963
3964 // static
ForWasm(Handle<String> name,Handle<WasmExportedFunctionData> exported_function_data,Handle<Map> map)3965 NewFunctionArgs NewFunctionArgs::ForWasm(
3966 Handle<String> name,
3967 Handle<WasmExportedFunctionData> exported_function_data, Handle<Map> map) {
3968 NewFunctionArgs args;
3969 args.name_ = name;
3970 args.maybe_map_ = map;
3971 args.maybe_exported_function_data_ = exported_function_data;
3972 args.language_mode_ = LanguageMode::kSloppy;
3973 args.prototype_mutability_ = MUTABLE;
3974
3975 return args;
3976 }
3977
3978 // static
ForBuiltin(Handle<String> name,Handle<Map> map,int builtin_id)3979 NewFunctionArgs NewFunctionArgs::ForBuiltin(Handle<String> name,
3980 Handle<Map> map, int builtin_id) {
3981 DCHECK(Builtins::IsBuiltinId(builtin_id));
3982
3983 NewFunctionArgs args;
3984 args.name_ = name;
3985 args.maybe_map_ = map;
3986 args.maybe_builtin_id_ = builtin_id;
3987 args.language_mode_ = LanguageMode::kStrict;
3988 args.prototype_mutability_ = MUTABLE;
3989
3990 args.SetShouldSetLanguageMode();
3991
3992 return args;
3993 }
3994
3995 // static
ForFunctionWithoutCode(Handle<String> name,Handle<Map> map,LanguageMode language_mode)3996 NewFunctionArgs NewFunctionArgs::ForFunctionWithoutCode(
3997 Handle<String> name, Handle<Map> map, LanguageMode language_mode) {
3998 NewFunctionArgs args;
3999 args.name_ = name;
4000 args.maybe_map_ = map;
4001 args.maybe_builtin_id_ = Builtins::kIllegal;
4002 args.language_mode_ = language_mode;
4003 args.prototype_mutability_ = MUTABLE;
4004
4005 args.SetShouldSetLanguageMode();
4006
4007 return args;
4008 }
4009
4010 // static
ForBuiltinWithPrototype(Handle<String> name,Handle<Object> prototype,InstanceType type,int instance_size,int inobject_properties,int builtin_id,MutableMode prototype_mutability)4011 NewFunctionArgs NewFunctionArgs::ForBuiltinWithPrototype(
4012 Handle<String> name, Handle<Object> prototype, InstanceType type,
4013 int instance_size, int inobject_properties, int builtin_id,
4014 MutableMode prototype_mutability) {
4015 DCHECK(Builtins::IsBuiltinId(builtin_id));
4016
4017 NewFunctionArgs args;
4018 args.name_ = name;
4019 args.type_ = type;
4020 args.instance_size_ = instance_size;
4021 args.inobject_properties_ = inobject_properties;
4022 args.maybe_prototype_ = prototype;
4023 args.maybe_builtin_id_ = builtin_id;
4024 args.language_mode_ = LanguageMode::kStrict;
4025 args.prototype_mutability_ = prototype_mutability;
4026
4027 args.SetShouldCreateAndSetInitialMap();
4028 args.SetShouldSetPrototype();
4029 args.SetShouldSetLanguageMode();
4030
4031 return args;
4032 }
4033
4034 // static
ForBuiltinWithoutPrototype(Handle<String> name,int builtin_id,LanguageMode language_mode)4035 NewFunctionArgs NewFunctionArgs::ForBuiltinWithoutPrototype(
4036 Handle<String> name, int builtin_id, LanguageMode language_mode) {
4037 DCHECK(Builtins::IsBuiltinId(builtin_id));
4038
4039 NewFunctionArgs args;
4040 args.name_ = name;
4041 args.maybe_builtin_id_ = builtin_id;
4042 args.language_mode_ = language_mode;
4043 args.prototype_mutability_ = MUTABLE;
4044
4045 args.SetShouldSetLanguageMode();
4046
4047 return args;
4048 }
4049
SetShouldCreateAndSetInitialMap()4050 void NewFunctionArgs::SetShouldCreateAndSetInitialMap() {
4051 // Needed to create the initial map.
4052 maybe_prototype_.Assert();
4053 DCHECK_NE(kUninitialized, instance_size_);
4054 DCHECK_NE(kUninitialized, inobject_properties_);
4055
4056 should_create_and_set_initial_map_ = true;
4057 }
4058
SetShouldSetPrototype()4059 void NewFunctionArgs::SetShouldSetPrototype() {
4060 maybe_prototype_.Assert();
4061 should_set_prototype_ = true;
4062 }
4063
SetShouldSetLanguageMode()4064 void NewFunctionArgs::SetShouldSetLanguageMode() {
4065 DCHECK(language_mode_ == LanguageMode::kStrict ||
4066 language_mode_ == LanguageMode::kSloppy);
4067 should_set_language_mode_ = true;
4068 }
4069
GetMap(Isolate * isolate) const4070 Handle<Map> NewFunctionArgs::GetMap(Isolate* isolate) const {
4071 if (!maybe_map_.is_null()) {
4072 return maybe_map_.ToHandleChecked();
4073 } else if (maybe_prototype_.is_null()) {
4074 return is_strict(language_mode_)
4075 ? isolate->strict_function_without_prototype_map()
4076 : isolate->sloppy_function_without_prototype_map();
4077 } else {
4078 DCHECK(!maybe_prototype_.is_null());
4079 switch (prototype_mutability_) {
4080 case MUTABLE:
4081 return is_strict(language_mode_) ? isolate->strict_function_map()
4082 : isolate->sloppy_function_map();
4083 case IMMUTABLE:
4084 return is_strict(language_mode_)
4085 ? isolate->strict_function_with_readonly_prototype_map()
4086 : isolate->sloppy_function_with_readonly_prototype_map();
4087 }
4088 }
4089 UNREACHABLE();
4090 }
4091
4092 } // namespace internal
4093 } // namespace v8
4094