1 // Copyright 2006-2008 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are
4 // met:
5 //
6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided
11 // with the distribution.
12 // * Neither the name of Google Inc. nor the names of its
13 // contributors may be used to endorse or promote products derived
14 // from this software without specific prior written permission.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28 #include "v8.h"
29
30 #include "api.h"
31 #include "debug.h"
32 #include "execution.h"
33 #include "factory.h"
34 #include "macro-assembler.h"
35
36 namespace v8 {
37 namespace internal {
38
39
NewFixedArray(int size,PretenureFlag pretenure)40 Handle<FixedArray> Factory::NewFixedArray(int size, PretenureFlag pretenure) {
41 ASSERT(0 <= size);
42 CALL_HEAP_FUNCTION(Heap::AllocateFixedArray(size, pretenure), FixedArray);
43 }
44
45
NewFixedArrayWithHoles(int size)46 Handle<FixedArray> Factory::NewFixedArrayWithHoles(int size) {
47 ASSERT(0 <= size);
48 CALL_HEAP_FUNCTION(Heap::AllocateFixedArrayWithHoles(size), FixedArray);
49 }
50
51
NewStringDictionary(int at_least_space_for)52 Handle<StringDictionary> Factory::NewStringDictionary(int at_least_space_for) {
53 ASSERT(0 <= at_least_space_for);
54 CALL_HEAP_FUNCTION(StringDictionary::Allocate(at_least_space_for),
55 StringDictionary);
56 }
57
58
NewNumberDictionary(int at_least_space_for)59 Handle<NumberDictionary> Factory::NewNumberDictionary(int at_least_space_for) {
60 ASSERT(0 <= at_least_space_for);
61 CALL_HEAP_FUNCTION(NumberDictionary::Allocate(at_least_space_for),
62 NumberDictionary);
63 }
64
65
NewDescriptorArray(int number_of_descriptors)66 Handle<DescriptorArray> Factory::NewDescriptorArray(int number_of_descriptors) {
67 ASSERT(0 <= number_of_descriptors);
68 CALL_HEAP_FUNCTION(DescriptorArray::Allocate(number_of_descriptors),
69 DescriptorArray);
70 }
71
72
73 // Symbols are created in the old generation (data space).
LookupSymbol(Vector<const char> string)74 Handle<String> Factory::LookupSymbol(Vector<const char> string) {
75 CALL_HEAP_FUNCTION(Heap::LookupSymbol(string), String);
76 }
77
78
NewStringFromAscii(Vector<const char> string,PretenureFlag pretenure)79 Handle<String> Factory::NewStringFromAscii(Vector<const char> string,
80 PretenureFlag pretenure) {
81 CALL_HEAP_FUNCTION(Heap::AllocateStringFromAscii(string, pretenure), String);
82 }
83
NewStringFromUtf8(Vector<const char> string,PretenureFlag pretenure)84 Handle<String> Factory::NewStringFromUtf8(Vector<const char> string,
85 PretenureFlag pretenure) {
86 CALL_HEAP_FUNCTION(Heap::AllocateStringFromUtf8(string, pretenure), String);
87 }
88
89
NewStringFromTwoByte(Vector<const uc16> string,PretenureFlag pretenure)90 Handle<String> Factory::NewStringFromTwoByte(Vector<const uc16> string,
91 PretenureFlag pretenure) {
92 CALL_HEAP_FUNCTION(Heap::AllocateStringFromTwoByte(string, pretenure),
93 String);
94 }
95
96
NewRawTwoByteString(int length,PretenureFlag pretenure)97 Handle<String> Factory::NewRawTwoByteString(int length,
98 PretenureFlag pretenure) {
99 CALL_HEAP_FUNCTION(Heap::AllocateRawTwoByteString(length, pretenure), String);
100 }
101
102
NewConsString(Handle<String> first,Handle<String> second)103 Handle<String> Factory::NewConsString(Handle<String> first,
104 Handle<String> second) {
105 CALL_HEAP_FUNCTION(Heap::AllocateConsString(*first, *second), String);
106 }
107
108
NewStringSlice(Handle<String> str,int begin,int end)109 Handle<String> Factory::NewStringSlice(Handle<String> str,
110 int begin,
111 int end) {
112 CALL_HEAP_FUNCTION(str->Slice(begin, end), String);
113 }
114
115
NewExternalStringFromAscii(ExternalAsciiString::Resource * resource)116 Handle<String> Factory::NewExternalStringFromAscii(
117 ExternalAsciiString::Resource* resource) {
118 CALL_HEAP_FUNCTION(Heap::AllocateExternalStringFromAscii(resource), String);
119 }
120
121
NewExternalStringFromTwoByte(ExternalTwoByteString::Resource * resource)122 Handle<String> Factory::NewExternalStringFromTwoByte(
123 ExternalTwoByteString::Resource* resource) {
124 CALL_HEAP_FUNCTION(Heap::AllocateExternalStringFromTwoByte(resource), String);
125 }
126
127
NewGlobalContext()128 Handle<Context> Factory::NewGlobalContext() {
129 CALL_HEAP_FUNCTION(Heap::AllocateGlobalContext(), Context);
130 }
131
132
NewFunctionContext(int length,Handle<JSFunction> closure)133 Handle<Context> Factory::NewFunctionContext(int length,
134 Handle<JSFunction> closure) {
135 CALL_HEAP_FUNCTION(Heap::AllocateFunctionContext(length, *closure), Context);
136 }
137
138
NewWithContext(Handle<Context> previous,Handle<JSObject> extension,bool is_catch_context)139 Handle<Context> Factory::NewWithContext(Handle<Context> previous,
140 Handle<JSObject> extension,
141 bool is_catch_context) {
142 CALL_HEAP_FUNCTION(Heap::AllocateWithContext(*previous,
143 *extension,
144 is_catch_context),
145 Context);
146 }
147
148
NewStruct(InstanceType type)149 Handle<Struct> Factory::NewStruct(InstanceType type) {
150 CALL_HEAP_FUNCTION(Heap::AllocateStruct(type), Struct);
151 }
152
153
NewAccessorInfo()154 Handle<AccessorInfo> Factory::NewAccessorInfo() {
155 Handle<AccessorInfo> info =
156 Handle<AccessorInfo>::cast(NewStruct(ACCESSOR_INFO_TYPE));
157 info->set_flag(0); // Must clear the flag, it was initialized as undefined.
158 return info;
159 }
160
161
NewScript(Handle<String> source)162 Handle<Script> Factory::NewScript(Handle<String> source) {
163 // Generate id for this script.
164 int id;
165 if (Heap::last_script_id()->IsUndefined()) {
166 // Script ids start from one.
167 id = 1;
168 } else {
169 // Increment id, wrap when positive smi is exhausted.
170 id = Smi::cast(Heap::last_script_id())->value();
171 id++;
172 if (!Smi::IsValid(id)) {
173 id = 0;
174 }
175 }
176 Heap::SetLastScriptId(Smi::FromInt(id));
177
178 // Create and initialize script object.
179 Handle<Proxy> wrapper = Factory::NewProxy(0, TENURED);
180 Handle<Script> script = Handle<Script>::cast(NewStruct(SCRIPT_TYPE));
181 script->set_source(*source);
182 script->set_name(Heap::undefined_value());
183 script->set_id(Heap::last_script_id());
184 script->set_line_offset(Smi::FromInt(0));
185 script->set_column_offset(Smi::FromInt(0));
186 script->set_data(Heap::undefined_value());
187 script->set_context_data(Heap::undefined_value());
188 script->set_type(Smi::FromInt(Script::TYPE_NORMAL));
189 script->set_compilation_type(Smi::FromInt(Script::COMPILATION_TYPE_HOST));
190 script->set_wrapper(*wrapper);
191 script->set_line_ends(Heap::undefined_value());
192 script->set_eval_from_function(Heap::undefined_value());
193 script->set_eval_from_instructions_offset(Smi::FromInt(0));
194
195 return script;
196 }
197
198
NewProxy(Address addr,PretenureFlag pretenure)199 Handle<Proxy> Factory::NewProxy(Address addr, PretenureFlag pretenure) {
200 CALL_HEAP_FUNCTION(Heap::AllocateProxy(addr, pretenure), Proxy);
201 }
202
203
NewProxy(const AccessorDescriptor * desc)204 Handle<Proxy> Factory::NewProxy(const AccessorDescriptor* desc) {
205 return NewProxy((Address) desc, TENURED);
206 }
207
208
NewByteArray(int length,PretenureFlag pretenure)209 Handle<ByteArray> Factory::NewByteArray(int length, PretenureFlag pretenure) {
210 ASSERT(0 <= length);
211 CALL_HEAP_FUNCTION(Heap::AllocateByteArray(length, pretenure), ByteArray);
212 }
213
214
NewPixelArray(int length,uint8_t * external_pointer,PretenureFlag pretenure)215 Handle<PixelArray> Factory::NewPixelArray(int length,
216 uint8_t* external_pointer,
217 PretenureFlag pretenure) {
218 ASSERT(0 <= length);
219 CALL_HEAP_FUNCTION(Heap::AllocatePixelArray(length,
220 external_pointer,
221 pretenure), PixelArray);
222 }
223
224
NewMap(InstanceType type,int instance_size)225 Handle<Map> Factory::NewMap(InstanceType type, int instance_size) {
226 CALL_HEAP_FUNCTION(Heap::AllocateMap(type, instance_size), Map);
227 }
228
229
NewFunctionPrototype(Handle<JSFunction> function)230 Handle<JSObject> Factory::NewFunctionPrototype(Handle<JSFunction> function) {
231 CALL_HEAP_FUNCTION(Heap::AllocateFunctionPrototype(*function), JSObject);
232 }
233
234
CopyMapDropDescriptors(Handle<Map> src)235 Handle<Map> Factory::CopyMapDropDescriptors(Handle<Map> src) {
236 CALL_HEAP_FUNCTION(src->CopyDropDescriptors(), Map);
237 }
238
239
CopyMap(Handle<Map> src,int extra_inobject_properties)240 Handle<Map> Factory::CopyMap(Handle<Map> src,
241 int extra_inobject_properties) {
242 Handle<Map> copy = CopyMapDropDescriptors(src);
243 // Check that we do not overflow the instance size when adding the
244 // extra inobject properties.
245 int instance_size_delta = extra_inobject_properties * kPointerSize;
246 int max_instance_size_delta =
247 JSObject::kMaxInstanceSize - copy->instance_size();
248 if (instance_size_delta > max_instance_size_delta) {
249 // If the instance size overflows, we allocate as many properties
250 // as we can as inobject properties.
251 instance_size_delta = max_instance_size_delta;
252 extra_inobject_properties = max_instance_size_delta >> kPointerSizeLog2;
253 }
254 // Adjust the map with the extra inobject properties.
255 int inobject_properties =
256 copy->inobject_properties() + extra_inobject_properties;
257 copy->set_inobject_properties(inobject_properties);
258 copy->set_unused_property_fields(inobject_properties);
259 copy->set_instance_size(copy->instance_size() + instance_size_delta);
260 return copy;
261 }
262
CopyMapDropTransitions(Handle<Map> src)263 Handle<Map> Factory::CopyMapDropTransitions(Handle<Map> src) {
264 CALL_HEAP_FUNCTION(src->CopyDropTransitions(), Map);
265 }
266
267
CopyFixedArray(Handle<FixedArray> array)268 Handle<FixedArray> Factory::CopyFixedArray(Handle<FixedArray> array) {
269 CALL_HEAP_FUNCTION(array->Copy(), FixedArray);
270 }
271
272
BaseNewFunctionFromBoilerplate(Handle<JSFunction> boilerplate,Handle<Map> function_map)273 Handle<JSFunction> Factory::BaseNewFunctionFromBoilerplate(
274 Handle<JSFunction> boilerplate,
275 Handle<Map> function_map) {
276 ASSERT(boilerplate->IsBoilerplate());
277 ASSERT(!boilerplate->has_initial_map());
278 ASSERT(!boilerplate->has_prototype());
279 ASSERT(boilerplate->properties() == Heap::empty_fixed_array());
280 ASSERT(boilerplate->elements() == Heap::empty_fixed_array());
281 CALL_HEAP_FUNCTION(Heap::AllocateFunction(*function_map,
282 boilerplate->shared(),
283 Heap::the_hole_value()),
284 JSFunction);
285 }
286
287
NewFunctionFromBoilerplate(Handle<JSFunction> boilerplate,Handle<Context> context)288 Handle<JSFunction> Factory::NewFunctionFromBoilerplate(
289 Handle<JSFunction> boilerplate,
290 Handle<Context> context) {
291 Handle<JSFunction> result =
292 BaseNewFunctionFromBoilerplate(boilerplate, Top::function_map());
293 result->set_context(*context);
294 int number_of_literals = boilerplate->NumberOfLiterals();
295 Handle<FixedArray> literals =
296 Factory::NewFixedArray(number_of_literals, TENURED);
297 if (number_of_literals > 0) {
298 // Store the object, regexp and array functions in the literals
299 // array prefix. These functions will be used when creating
300 // object, regexp and array literals in this function.
301 literals->set(JSFunction::kLiteralGlobalContextIndex,
302 context->global_context());
303 }
304 result->set_literals(*literals);
305 ASSERT(!result->IsBoilerplate());
306 return result;
307 }
308
309
NewNumber(double value,PretenureFlag pretenure)310 Handle<Object> Factory::NewNumber(double value,
311 PretenureFlag pretenure) {
312 CALL_HEAP_FUNCTION(Heap::NumberFromDouble(value, pretenure), Object);
313 }
314
315
NewNumberFromInt(int value)316 Handle<Object> Factory::NewNumberFromInt(int value) {
317 CALL_HEAP_FUNCTION(Heap::NumberFromInt32(value), Object);
318 }
319
320
NewNumberFromUint(uint32_t value)321 Handle<Object> Factory::NewNumberFromUint(uint32_t value) {
322 CALL_HEAP_FUNCTION(Heap::NumberFromUint32(value), Object);
323 }
324
325
NewNeanderObject()326 Handle<JSObject> Factory::NewNeanderObject() {
327 CALL_HEAP_FUNCTION(Heap::AllocateJSObjectFromMap(Heap::neander_map()),
328 JSObject);
329 }
330
331
NewTypeError(const char * type,Vector<Handle<Object>> args)332 Handle<Object> Factory::NewTypeError(const char* type,
333 Vector< Handle<Object> > args) {
334 return NewError("MakeTypeError", type, args);
335 }
336
337
NewTypeError(Handle<String> message)338 Handle<Object> Factory::NewTypeError(Handle<String> message) {
339 return NewError("$TypeError", message);
340 }
341
342
NewRangeError(const char * type,Vector<Handle<Object>> args)343 Handle<Object> Factory::NewRangeError(const char* type,
344 Vector< Handle<Object> > args) {
345 return NewError("MakeRangeError", type, args);
346 }
347
348
NewRangeError(Handle<String> message)349 Handle<Object> Factory::NewRangeError(Handle<String> message) {
350 return NewError("$RangeError", message);
351 }
352
353
NewSyntaxError(const char * type,Handle<JSArray> args)354 Handle<Object> Factory::NewSyntaxError(const char* type, Handle<JSArray> args) {
355 return NewError("MakeSyntaxError", type, args);
356 }
357
358
NewSyntaxError(Handle<String> message)359 Handle<Object> Factory::NewSyntaxError(Handle<String> message) {
360 return NewError("$SyntaxError", message);
361 }
362
363
NewReferenceError(const char * type,Vector<Handle<Object>> args)364 Handle<Object> Factory::NewReferenceError(const char* type,
365 Vector< Handle<Object> > args) {
366 return NewError("MakeReferenceError", type, args);
367 }
368
369
NewReferenceError(Handle<String> message)370 Handle<Object> Factory::NewReferenceError(Handle<String> message) {
371 return NewError("$ReferenceError", message);
372 }
373
374
NewError(const char * maker,const char * type,Vector<Handle<Object>> args)375 Handle<Object> Factory::NewError(const char* maker, const char* type,
376 Vector< Handle<Object> > args) {
377 v8::HandleScope scope; // Instantiate a closeable HandleScope for EscapeFrom.
378 Handle<FixedArray> array = Factory::NewFixedArray(args.length());
379 for (int i = 0; i < args.length(); i++) {
380 array->set(i, *args[i]);
381 }
382 Handle<JSArray> object = Factory::NewJSArrayWithElements(array);
383 Handle<Object> result = NewError(maker, type, object);
384 return result.EscapeFrom(&scope);
385 }
386
387
NewEvalError(const char * type,Vector<Handle<Object>> args)388 Handle<Object> Factory::NewEvalError(const char* type,
389 Vector< Handle<Object> > args) {
390 return NewError("MakeEvalError", type, args);
391 }
392
393
NewError(const char * type,Vector<Handle<Object>> args)394 Handle<Object> Factory::NewError(const char* type,
395 Vector< Handle<Object> > args) {
396 return NewError("MakeError", type, args);
397 }
398
399
NewError(const char * maker,const char * type,Handle<JSArray> args)400 Handle<Object> Factory::NewError(const char* maker,
401 const char* type,
402 Handle<JSArray> args) {
403 Handle<String> make_str = Factory::LookupAsciiSymbol(maker);
404 Handle<JSFunction> fun =
405 Handle<JSFunction>(
406 JSFunction::cast(
407 Top::builtins()->GetProperty(*make_str)));
408 Handle<Object> type_obj = Factory::LookupAsciiSymbol(type);
409 Object** argv[2] = { type_obj.location(),
410 Handle<Object>::cast(args).location() };
411
412 // Invoke the JavaScript factory method. If an exception is thrown while
413 // running the factory method, use the exception as the result.
414 bool caught_exception;
415 Handle<Object> result = Execution::TryCall(fun,
416 Top::builtins(),
417 2,
418 argv,
419 &caught_exception);
420 return result;
421 }
422
423
NewError(Handle<String> message)424 Handle<Object> Factory::NewError(Handle<String> message) {
425 return NewError("$Error", message);
426 }
427
428
NewError(const char * constructor,Handle<String> message)429 Handle<Object> Factory::NewError(const char* constructor,
430 Handle<String> message) {
431 Handle<String> constr = Factory::LookupAsciiSymbol(constructor);
432 Handle<JSFunction> fun =
433 Handle<JSFunction>(
434 JSFunction::cast(
435 Top::builtins()->GetProperty(*constr)));
436 Object** argv[1] = { Handle<Object>::cast(message).location() };
437
438 // Invoke the JavaScript factory method. If an exception is thrown while
439 // running the factory method, use the exception as the result.
440 bool caught_exception;
441 Handle<Object> result = Execution::TryCall(fun,
442 Top::builtins(),
443 1,
444 argv,
445 &caught_exception);
446 return result;
447 }
448
449
NewFunction(Handle<String> name,InstanceType type,int instance_size,Handle<Code> code,bool force_initial_map)450 Handle<JSFunction> Factory::NewFunction(Handle<String> name,
451 InstanceType type,
452 int instance_size,
453 Handle<Code> code,
454 bool force_initial_map) {
455 // Allocate the function
456 Handle<JSFunction> function = NewFunction(name, the_hole_value());
457 function->set_code(*code);
458
459 if (force_initial_map ||
460 type != JS_OBJECT_TYPE ||
461 instance_size != JSObject::kHeaderSize) {
462 Handle<Map> initial_map = NewMap(type, instance_size);
463 Handle<JSObject> prototype = NewFunctionPrototype(function);
464 initial_map->set_prototype(*prototype);
465 function->set_initial_map(*initial_map);
466 initial_map->set_constructor(*function);
467 } else {
468 ASSERT(!function->has_initial_map());
469 ASSERT(!function->has_prototype());
470 }
471
472 return function;
473 }
474
475
NewFunctionBoilerplate(Handle<String> name,int number_of_literals,bool contains_array_literal,Handle<Code> code)476 Handle<JSFunction> Factory::NewFunctionBoilerplate(Handle<String> name,
477 int number_of_literals,
478 bool contains_array_literal,
479 Handle<Code> code) {
480 Handle<JSFunction> function = NewFunctionBoilerplate(name);
481 function->set_code(*code);
482 int literals_array_size = number_of_literals;
483 // If the function contains object, regexp or array literals,
484 // allocate extra space for a literals array prefix containing the
485 // object, regexp and array constructor functions.
486 if (number_of_literals > 0 || contains_array_literal) {
487 literals_array_size += JSFunction::kLiteralsPrefixSize;
488 }
489 Handle<FixedArray> literals =
490 Factory::NewFixedArray(literals_array_size, TENURED);
491 function->set_literals(*literals);
492 ASSERT(!function->has_initial_map());
493 ASSERT(!function->has_prototype());
494 return function;
495 }
496
497
NewFunctionBoilerplate(Handle<String> name)498 Handle<JSFunction> Factory::NewFunctionBoilerplate(Handle<String> name) {
499 Handle<SharedFunctionInfo> shared = NewSharedFunctionInfo(name);
500 CALL_HEAP_FUNCTION(Heap::AllocateFunction(Heap::boilerplate_function_map(),
501 *shared,
502 Heap::the_hole_value()),
503 JSFunction);
504 }
505
506
NewFunctionWithPrototype(Handle<String> name,InstanceType type,int instance_size,Handle<JSObject> prototype,Handle<Code> code,bool force_initial_map)507 Handle<JSFunction> Factory::NewFunctionWithPrototype(Handle<String> name,
508 InstanceType type,
509 int instance_size,
510 Handle<JSObject> prototype,
511 Handle<Code> code,
512 bool force_initial_map) {
513 // Allocate the function
514 Handle<JSFunction> function = NewFunction(name, prototype);
515
516 function->set_code(*code);
517
518 if (force_initial_map ||
519 type != JS_OBJECT_TYPE ||
520 instance_size != JSObject::kHeaderSize) {
521 Handle<Map> initial_map = NewMap(type, instance_size);
522 function->set_initial_map(*initial_map);
523 initial_map->set_constructor(*function);
524 }
525
526 // Set function.prototype and give the prototype a constructor
527 // property that refers to the function.
528 SetPrototypeProperty(function, prototype);
529 SetProperty(prototype, Factory::constructor_symbol(), function, DONT_ENUM);
530 return function;
531 }
532
533
NewCode(const CodeDesc & desc,ZoneScopeInfo * sinfo,Code::Flags flags,Handle<Object> self_ref)534 Handle<Code> Factory::NewCode(const CodeDesc& desc,
535 ZoneScopeInfo* sinfo,
536 Code::Flags flags,
537 Handle<Object> self_ref) {
538 CALL_HEAP_FUNCTION(Heap::CreateCode(desc, sinfo, flags, self_ref), Code);
539 }
540
541
CopyCode(Handle<Code> code)542 Handle<Code> Factory::CopyCode(Handle<Code> code) {
543 CALL_HEAP_FUNCTION(Heap::CopyCode(*code), Code);
544 }
545
546
DoCopyInsert(DescriptorArray * array,String * key,Object * value,PropertyAttributes attributes)547 static inline Object* DoCopyInsert(DescriptorArray* array,
548 String* key,
549 Object* value,
550 PropertyAttributes attributes) {
551 CallbacksDescriptor desc(key, value, attributes);
552 Object* obj = array->CopyInsert(&desc, REMOVE_TRANSITIONS);
553 return obj;
554 }
555
556
557 // Allocate the new array.
CopyAppendProxyDescriptor(Handle<DescriptorArray> array,Handle<String> key,Handle<Object> value,PropertyAttributes attributes)558 Handle<DescriptorArray> Factory::CopyAppendProxyDescriptor(
559 Handle<DescriptorArray> array,
560 Handle<String> key,
561 Handle<Object> value,
562 PropertyAttributes attributes) {
563 CALL_HEAP_FUNCTION(DoCopyInsert(*array, *key, *value, attributes),
564 DescriptorArray);
565 }
566
567
SymbolFromString(Handle<String> value)568 Handle<String> Factory::SymbolFromString(Handle<String> value) {
569 CALL_HEAP_FUNCTION(Heap::LookupSymbol(*value), String);
570 }
571
572
CopyAppendCallbackDescriptors(Handle<DescriptorArray> array,Handle<Object> descriptors)573 Handle<DescriptorArray> Factory::CopyAppendCallbackDescriptors(
574 Handle<DescriptorArray> array,
575 Handle<Object> descriptors) {
576 v8::NeanderArray callbacks(descriptors);
577 int nof_callbacks = callbacks.length();
578 Handle<DescriptorArray> result =
579 NewDescriptorArray(array->number_of_descriptors() + nof_callbacks);
580
581 // Number of descriptors added to the result so far.
582 int descriptor_count = 0;
583
584 // Copy the descriptors from the array.
585 for (int i = 0; i < array->number_of_descriptors(); i++) {
586 if (array->GetType(i) != NULL_DESCRIPTOR) {
587 result->CopyFrom(descriptor_count++, *array, i);
588 }
589 }
590
591 // Number of duplicates detected.
592 int duplicates = 0;
593
594 // Fill in new callback descriptors. Process the callbacks from
595 // back to front so that the last callback with a given name takes
596 // precedence over previously added callbacks with that name.
597 for (int i = nof_callbacks - 1; i >= 0; i--) {
598 Handle<AccessorInfo> entry =
599 Handle<AccessorInfo>(AccessorInfo::cast(callbacks.get(i)));
600 // Ensure the key is a symbol before writing into the instance descriptor.
601 Handle<String> key =
602 SymbolFromString(Handle<String>(String::cast(entry->name())));
603 // Check if a descriptor with this name already exists before writing.
604 if (result->LinearSearch(*key, descriptor_count) ==
605 DescriptorArray::kNotFound) {
606 CallbacksDescriptor desc(*key, *entry, entry->property_attributes());
607 result->Set(descriptor_count, &desc);
608 descriptor_count++;
609 } else {
610 duplicates++;
611 }
612 }
613
614 // If duplicates were detected, allocate a result of the right size
615 // and transfer the elements.
616 if (duplicates > 0) {
617 int number_of_descriptors = result->number_of_descriptors() - duplicates;
618 Handle<DescriptorArray> new_result =
619 NewDescriptorArray(number_of_descriptors);
620 for (int i = 0; i < number_of_descriptors; i++) {
621 new_result->CopyFrom(i, *result, i);
622 }
623 result = new_result;
624 }
625
626 // Sort the result before returning.
627 result->Sort();
628 return result;
629 }
630
631
NewJSObject(Handle<JSFunction> constructor,PretenureFlag pretenure)632 Handle<JSObject> Factory::NewJSObject(Handle<JSFunction> constructor,
633 PretenureFlag pretenure) {
634 CALL_HEAP_FUNCTION(Heap::AllocateJSObject(*constructor, pretenure), JSObject);
635 }
636
637
NewGlobalObject(Handle<JSFunction> constructor)638 Handle<GlobalObject> Factory::NewGlobalObject(
639 Handle<JSFunction> constructor) {
640 CALL_HEAP_FUNCTION(Heap::AllocateGlobalObject(*constructor),
641 GlobalObject);
642 }
643
644
645
NewJSObjectFromMap(Handle<Map> map)646 Handle<JSObject> Factory::NewJSObjectFromMap(Handle<Map> map) {
647 CALL_HEAP_FUNCTION(Heap::AllocateJSObjectFromMap(*map, NOT_TENURED),
648 JSObject);
649 }
650
651
NewJSArray(int length,PretenureFlag pretenure)652 Handle<JSArray> Factory::NewJSArray(int length,
653 PretenureFlag pretenure) {
654 Handle<JSObject> obj = NewJSObject(Top::array_function(), pretenure);
655 CALL_HEAP_FUNCTION(Handle<JSArray>::cast(obj)->Initialize(length), JSArray);
656 }
657
658
NewJSArrayWithElements(Handle<FixedArray> elements,PretenureFlag pretenure)659 Handle<JSArray> Factory::NewJSArrayWithElements(Handle<FixedArray> elements,
660 PretenureFlag pretenure) {
661 Handle<JSArray> result =
662 Handle<JSArray>::cast(NewJSObject(Top::array_function(), pretenure));
663 result->SetContent(*elements);
664 return result;
665 }
666
667
NewSharedFunctionInfo(Handle<String> name)668 Handle<SharedFunctionInfo> Factory::NewSharedFunctionInfo(Handle<String> name) {
669 CALL_HEAP_FUNCTION(Heap::AllocateSharedFunctionInfo(*name),
670 SharedFunctionInfo);
671 }
672
673
DictionaryAtNumberPut(Handle<NumberDictionary> dictionary,uint32_t key,Handle<Object> value)674 Handle<NumberDictionary> Factory::DictionaryAtNumberPut(
675 Handle<NumberDictionary> dictionary,
676 uint32_t key,
677 Handle<Object> value) {
678 CALL_HEAP_FUNCTION(dictionary->AtNumberPut(key, *value), NumberDictionary);
679 }
680
681
NewFunctionHelper(Handle<String> name,Handle<Object> prototype)682 Handle<JSFunction> Factory::NewFunctionHelper(Handle<String> name,
683 Handle<Object> prototype) {
684 Handle<SharedFunctionInfo> function_share = NewSharedFunctionInfo(name);
685 CALL_HEAP_FUNCTION(Heap::AllocateFunction(*Top::function_map(),
686 *function_share,
687 *prototype),
688 JSFunction);
689 }
690
691
NewFunction(Handle<String> name,Handle<Object> prototype)692 Handle<JSFunction> Factory::NewFunction(Handle<String> name,
693 Handle<Object> prototype) {
694 Handle<JSFunction> fun = NewFunctionHelper(name, prototype);
695 fun->set_context(Top::context()->global_context());
696 return fun;
697 }
698
699
ToObject(Handle<Object> object,Handle<Context> global_context)700 Handle<Object> Factory::ToObject(Handle<Object> object,
701 Handle<Context> global_context) {
702 CALL_HEAP_FUNCTION(object->ToObject(*global_context), Object);
703 }
704
705
706 #ifdef ENABLE_DEBUGGER_SUPPORT
NewDebugInfo(Handle<SharedFunctionInfo> shared)707 Handle<DebugInfo> Factory::NewDebugInfo(Handle<SharedFunctionInfo> shared) {
708 // Get the original code of the function.
709 Handle<Code> code(shared->code());
710
711 // Create a copy of the code before allocating the debug info object to avoid
712 // allocation while setting up the debug info object.
713 Handle<Code> original_code(*Factory::CopyCode(code));
714
715 // Allocate initial fixed array for active break points before allocating the
716 // debug info object to avoid allocation while setting up the debug info
717 // object.
718 Handle<FixedArray> break_points(
719 Factory::NewFixedArray(Debug::kEstimatedNofBreakPointsInFunction));
720
721 // Create and set up the debug info object. Debug info contains function, a
722 // copy of the original code, the executing code and initial fixed array for
723 // active break points.
724 Handle<DebugInfo> debug_info =
725 Handle<DebugInfo>::cast(Factory::NewStruct(DEBUG_INFO_TYPE));
726 debug_info->set_shared(*shared);
727 debug_info->set_original_code(*original_code);
728 debug_info->set_code(*code);
729 debug_info->set_break_points(*break_points);
730
731 // Link debug info to function.
732 shared->set_debug_info(*debug_info);
733
734 return debug_info;
735 }
736 #endif
737
738
NewArgumentsObject(Handle<Object> callee,int length)739 Handle<JSObject> Factory::NewArgumentsObject(Handle<Object> callee,
740 int length) {
741 CALL_HEAP_FUNCTION(Heap::AllocateArgumentsObject(*callee, length), JSObject);
742 }
743
744
CreateApiFunction(Handle<FunctionTemplateInfo> obj,ApiInstanceType instance_type)745 Handle<JSFunction> Factory::CreateApiFunction(
746 Handle<FunctionTemplateInfo> obj, ApiInstanceType instance_type) {
747 Handle<Code> code = Handle<Code>(Builtins::builtin(Builtins::HandleApiCall));
748
749 int internal_field_count = 0;
750 if (!obj->instance_template()->IsUndefined()) {
751 Handle<ObjectTemplateInfo> instance_template =
752 Handle<ObjectTemplateInfo>(
753 ObjectTemplateInfo::cast(obj->instance_template()));
754 internal_field_count =
755 Smi::cast(instance_template->internal_field_count())->value();
756 }
757
758 int instance_size = kPointerSize * internal_field_count;
759 InstanceType type = INVALID_TYPE;
760 switch (instance_type) {
761 case JavaScriptObject:
762 type = JS_OBJECT_TYPE;
763 instance_size += JSObject::kHeaderSize;
764 break;
765 case InnerGlobalObject:
766 type = JS_GLOBAL_OBJECT_TYPE;
767 instance_size += JSGlobalObject::kSize;
768 break;
769 case OuterGlobalObject:
770 type = JS_GLOBAL_PROXY_TYPE;
771 instance_size += JSGlobalProxy::kSize;
772 break;
773 default:
774 break;
775 }
776 ASSERT(type != INVALID_TYPE);
777
778 Handle<JSFunction> result =
779 Factory::NewFunction(Factory::empty_symbol(),
780 type,
781 instance_size,
782 code,
783 true);
784 // Set class name.
785 Handle<Object> class_name = Handle<Object>(obj->class_name());
786 if (class_name->IsString()) {
787 result->shared()->set_instance_class_name(*class_name);
788 result->shared()->set_name(*class_name);
789 }
790
791 Handle<Map> map = Handle<Map>(result->initial_map());
792
793 // Mark as undetectable if needed.
794 if (obj->undetectable()) {
795 map->set_is_undetectable();
796 }
797
798 // Mark as hidden for the __proto__ accessor if needed.
799 if (obj->hidden_prototype()) {
800 map->set_is_hidden_prototype();
801 }
802
803 // Mark as needs_access_check if needed.
804 if (obj->needs_access_check()) {
805 map->set_is_access_check_needed(true);
806 }
807
808 // Set interceptor information in the map.
809 if (!obj->named_property_handler()->IsUndefined()) {
810 map->set_has_named_interceptor();
811 }
812 if (!obj->indexed_property_handler()->IsUndefined()) {
813 map->set_has_indexed_interceptor();
814 }
815
816 // Set instance call-as-function information in the map.
817 if (!obj->instance_call_handler()->IsUndefined()) {
818 map->set_has_instance_call_handler();
819 }
820
821 result->shared()->set_function_data(*obj);
822 result->shared()->DontAdaptArguments();
823
824 // Recursively copy parent templates' accessors, 'data' may be modified.
825 Handle<DescriptorArray> array =
826 Handle<DescriptorArray>(map->instance_descriptors());
827 while (true) {
828 Handle<Object> props = Handle<Object>(obj->property_accessors());
829 if (!props->IsUndefined()) {
830 array = Factory::CopyAppendCallbackDescriptors(array, props);
831 }
832 Handle<Object> parent = Handle<Object>(obj->parent_template());
833 if (parent->IsUndefined()) break;
834 obj = Handle<FunctionTemplateInfo>::cast(parent);
835 }
836 if (!array->IsEmpty()) {
837 map->set_instance_descriptors(*array);
838 }
839
840 return result;
841 }
842
843
NewMapCache(int at_least_space_for)844 Handle<MapCache> Factory::NewMapCache(int at_least_space_for) {
845 CALL_HEAP_FUNCTION(MapCache::Allocate(at_least_space_for), MapCache);
846 }
847
848
UpdateMapCacheWith(Context * context,FixedArray * keys,Map * map)849 static Object* UpdateMapCacheWith(Context* context,
850 FixedArray* keys,
851 Map* map) {
852 Object* result = MapCache::cast(context->map_cache())->Put(keys, map);
853 if (!result->IsFailure()) context->set_map_cache(MapCache::cast(result));
854 return result;
855 }
856
857
AddToMapCache(Handle<Context> context,Handle<FixedArray> keys,Handle<Map> map)858 Handle<MapCache> Factory::AddToMapCache(Handle<Context> context,
859 Handle<FixedArray> keys,
860 Handle<Map> map) {
861 CALL_HEAP_FUNCTION(UpdateMapCacheWith(*context, *keys, *map), MapCache);
862 }
863
864
ObjectLiteralMapFromCache(Handle<Context> context,Handle<FixedArray> keys)865 Handle<Map> Factory::ObjectLiteralMapFromCache(Handle<Context> context,
866 Handle<FixedArray> keys) {
867 if (context->map_cache()->IsUndefined()) {
868 // Allocate the new map cache for the global context.
869 Handle<MapCache> new_cache = NewMapCache(24);
870 context->set_map_cache(*new_cache);
871 }
872 // Check to see whether there is a matching element in the cache.
873 Handle<MapCache> cache =
874 Handle<MapCache>(MapCache::cast(context->map_cache()));
875 Handle<Object> result = Handle<Object>(cache->Lookup(*keys));
876 if (result->IsMap()) return Handle<Map>::cast(result);
877 // Create a new map and add it to the cache.
878 Handle<Map> map =
879 CopyMap(Handle<Map>(context->object_function()->initial_map()),
880 keys->length());
881 AddToMapCache(context, keys, map);
882 return Handle<Map>(map);
883 }
884
885
SetRegExpAtomData(Handle<JSRegExp> regexp,JSRegExp::Type type,Handle<String> source,JSRegExp::Flags flags,Handle<Object> data)886 void Factory::SetRegExpAtomData(Handle<JSRegExp> regexp,
887 JSRegExp::Type type,
888 Handle<String> source,
889 JSRegExp::Flags flags,
890 Handle<Object> data) {
891 Handle<FixedArray> store = NewFixedArray(JSRegExp::kAtomDataSize);
892
893 store->set(JSRegExp::kTagIndex, Smi::FromInt(type));
894 store->set(JSRegExp::kSourceIndex, *source);
895 store->set(JSRegExp::kFlagsIndex, Smi::FromInt(flags.value()));
896 store->set(JSRegExp::kAtomPatternIndex, *data);
897 regexp->set_data(*store);
898 }
899
SetRegExpIrregexpData(Handle<JSRegExp> regexp,JSRegExp::Type type,Handle<String> source,JSRegExp::Flags flags,int capture_count)900 void Factory::SetRegExpIrregexpData(Handle<JSRegExp> regexp,
901 JSRegExp::Type type,
902 Handle<String> source,
903 JSRegExp::Flags flags,
904 int capture_count) {
905 Handle<FixedArray> store = NewFixedArray(JSRegExp::kIrregexpDataSize);
906
907 store->set(JSRegExp::kTagIndex, Smi::FromInt(type));
908 store->set(JSRegExp::kSourceIndex, *source);
909 store->set(JSRegExp::kFlagsIndex, Smi::FromInt(flags.value()));
910 store->set(JSRegExp::kIrregexpASCIICodeIndex, Heap::the_hole_value());
911 store->set(JSRegExp::kIrregexpUC16CodeIndex, Heap::the_hole_value());
912 store->set(JSRegExp::kIrregexpMaxRegisterCountIndex, Smi::FromInt(0));
913 store->set(JSRegExp::kIrregexpCaptureCountIndex,
914 Smi::FromInt(capture_count));
915 regexp->set_data(*store);
916 }
917
918
919
ConfigureInstance(Handle<FunctionTemplateInfo> desc,Handle<JSObject> instance,bool * pending_exception)920 void Factory::ConfigureInstance(Handle<FunctionTemplateInfo> desc,
921 Handle<JSObject> instance,
922 bool* pending_exception) {
923 // Configure the instance by adding the properties specified by the
924 // instance template.
925 Handle<Object> instance_template = Handle<Object>(desc->instance_template());
926 if (!instance_template->IsUndefined()) {
927 Execution::ConfigureInstance(instance,
928 instance_template,
929 pending_exception);
930 } else {
931 *pending_exception = false;
932 }
933 }
934
935
936 } } // namespace v8::internal
937