blob: 3167a71b9d3008b732861db4d1cc38517d09d070 [file] [log] [blame]
ager@chromium.org9258b6b2008-09-11 09:11:10 +00001// Copyright 2006-2008 the V8 project authors. All rights reserved.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002// 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"
v8.team.kasperl727e9952008-09-02 14:56:44 +000031#include "debug.h"
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000032#include "execution.h"
33#include "factory.h"
34#include "macro-assembler.h"
35
36namespace v8 { namespace internal {
37
38
39Handle<FixedArray> Factory::NewFixedArray(int size, PretenureFlag pretenure) {
40 ASSERT(0 <= size);
41 CALL_HEAP_FUNCTION(Heap::AllocateFixedArray(size, pretenure), FixedArray);
42}
43
44
45Handle<DescriptorArray> Factory::NewDescriptorArray(int number_of_descriptors) {
46 ASSERT(0 <= number_of_descriptors);
47 CALL_HEAP_FUNCTION(DescriptorArray::Allocate(number_of_descriptors),
48 DescriptorArray);
49}
50
51
ager@chromium.org9258b6b2008-09-11 09:11:10 +000052// Symbols are created in the old generation (data space).
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000053Handle<String> Factory::LookupSymbol(Vector<const char> string) {
54 CALL_HEAP_FUNCTION(Heap::LookupSymbol(string), String);
55}
56
57
58Handle<String> Factory::NewStringFromAscii(Vector<const char> string,
59 PretenureFlag pretenure) {
60 CALL_HEAP_FUNCTION(Heap::AllocateStringFromAscii(string, pretenure), String);
61}
62
63Handle<String> Factory::NewStringFromUtf8(Vector<const char> string,
64 PretenureFlag pretenure) {
65 CALL_HEAP_FUNCTION(Heap::AllocateStringFromUtf8(string, pretenure), String);
66}
67
68
69Handle<String> Factory::NewStringFromTwoByte(Vector<const uc16> string) {
70 CALL_HEAP_FUNCTION(Heap::AllocateStringFromTwoByte(string), String);
71}
72
73
74Handle<String> Factory::NewRawTwoByteString(int length,
75 PretenureFlag pretenure) {
76 CALL_HEAP_FUNCTION(Heap::AllocateRawTwoByteString(length, pretenure), String);
77}
78
79
80Handle<String> Factory::NewConsString(Handle<String> first,
81 Handle<String> second) {
82 CALL_HEAP_FUNCTION(Heap::AllocateConsString(*first, *second), String);
83}
84
85
86Handle<String> Factory::NewStringSlice(Handle<String> str, int begin, int end) {
87 CALL_HEAP_FUNCTION(str->Slice(begin, end), String);
88}
89
90
91Handle<String> Factory::NewExternalStringFromAscii(
92 ExternalAsciiString::Resource* resource) {
93 CALL_HEAP_FUNCTION(Heap::AllocateExternalStringFromAscii(resource), String);
94}
95
96
97Handle<String> Factory::NewExternalStringFromTwoByte(
98 ExternalTwoByteString::Resource* resource) {
99 CALL_HEAP_FUNCTION(Heap::AllocateExternalStringFromTwoByte(resource), String);
100}
101
102
103Handle<Context> Factory::NewGlobalContext() {
104 CALL_HEAP_FUNCTION(Heap::AllocateGlobalContext(), Context);
105}
106
107
108Handle<Context> Factory::NewFunctionContext(int length,
109 Handle<JSFunction> closure) {
110 CALL_HEAP_FUNCTION(Heap::AllocateFunctionContext(length, *closure), Context);
111}
112
113
114Handle<Context> Factory::NewWithContext(Handle<Context> previous,
115 Handle<JSObject> extension) {
116 CALL_HEAP_FUNCTION(Heap::AllocateWithContext(*previous, *extension), Context);
117}
118
119
120Handle<Struct> Factory::NewStruct(InstanceType type) {
121 CALL_HEAP_FUNCTION(Heap::AllocateStruct(type), Struct);
122}
123
124
125Handle<AccessorInfo> Factory::NewAccessorInfo() {
126 Handle<AccessorInfo> info =
127 Handle<AccessorInfo>::cast(NewStruct(ACCESSOR_INFO_TYPE));
128 info->set_flag(0); // Must clear the flag, it was initialized as undefined.
129 return info;
130}
131
132
133Handle<Script> Factory::NewScript(Handle<String> source) {
134 Handle<Script> script = Handle<Script>::cast(NewStruct(SCRIPT_TYPE));
135 script->set_source(*source);
136 script->set_name(Heap::undefined_value());
137 script->set_line_offset(Smi::FromInt(0));
138 script->set_column_offset(Smi::FromInt(0));
139 script->set_wrapper(*Factory::NewProxy(0, TENURED));
140 script->set_type(Smi::FromInt(SCRIPT_TYPE_NORMAL));
141 return script;
142}
143
144
145Handle<Proxy> Factory::NewProxy(Address addr, PretenureFlag pretenure) {
146 CALL_HEAP_FUNCTION(Heap::AllocateProxy(addr, pretenure), Proxy);
147}
148
149
150Handle<Proxy> Factory::NewProxy(const AccessorDescriptor* desc) {
151 return NewProxy((Address) desc, TENURED);
152}
153
154
155Handle<ByteArray> Factory::NewByteArray(int length) {
156 ASSERT(0 <= length);
157 CALL_HEAP_FUNCTION(Heap::AllocateByteArray(length), ByteArray);
158}
159
160
161Handle<Map> Factory::NewMap(InstanceType type, int instance_size) {
162 CALL_HEAP_FUNCTION(Heap::AllocateMap(type, instance_size), Map);
163}
164
165
166Handle<JSObject> Factory::NewFunctionPrototype(Handle<JSFunction> function) {
167 CALL_HEAP_FUNCTION(Heap::AllocateFunctionPrototype(*function), JSObject);
168}
169
170
171Handle<Map> Factory::CopyMap(Handle<Map> src) {
172 CALL_HEAP_FUNCTION(src->Copy(), Map);
173}
174
175
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000176Handle<Map> Factory::CopyMapDropTransitions(Handle<Map> src) {
177 CALL_HEAP_FUNCTION(src->CopyDropTransitions(), Map);
178}
179
180
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000181Handle<FixedArray> Factory::CopyFixedArray(Handle<FixedArray> array) {
182 CALL_HEAP_FUNCTION(array->Copy(), FixedArray);
183}
184
185
186Handle<JSFunction> Factory::BaseNewFunctionFromBoilerplate(
187 Handle<JSFunction> boilerplate,
188 Handle<Map> function_map) {
189 ASSERT(boilerplate->IsBoilerplate());
190 ASSERT(!boilerplate->has_initial_map());
191 ASSERT(!boilerplate->has_prototype());
192 ASSERT(boilerplate->properties() == Heap::empty_fixed_array());
193 ASSERT(boilerplate->elements() == Heap::empty_fixed_array());
194 CALL_HEAP_FUNCTION(Heap::AllocateFunction(*function_map,
195 boilerplate->shared(),
196 Heap::the_hole_value()),
197 JSFunction);
198}
199
200
201Handle<JSFunction> Factory::NewFunctionFromBoilerplate(
202 Handle<JSFunction> boilerplate,
203 Handle<Context> context) {
204 Handle<JSFunction> result =
205 BaseNewFunctionFromBoilerplate(boilerplate, Top::function_map());
206 result->set_context(*context);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000207 int number_of_literals = boilerplate->NumberOfLiterals();
208 Handle<FixedArray> literals =
209 Factory::NewFixedArray(number_of_literals, TENURED);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000210 if (number_of_literals > 0) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000211 // Store the object, regexp and array functions in the literals
212 // array prefix. These functions will be used when creating
213 // object, regexp and array literals in this function.
ager@chromium.org236ad962008-09-25 09:45:57 +0000214 literals->set(JSFunction::kLiteralGlobalContextIndex,
215 context->global_context());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000216 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000217 result->set_literals(*literals);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000218 ASSERT(!result->IsBoilerplate());
219 return result;
220}
221
222
223Handle<Object> Factory::NewNumber(double value,
224 PretenureFlag pretenure) {
225 CALL_HEAP_FUNCTION(Heap::NumberFromDouble(value, pretenure), Object);
226}
227
228
229Handle<Object> Factory::NewNumberFromInt(int value) {
230 CALL_HEAP_FUNCTION(Heap::NumberFromInt32(value), Object);
231}
232
233
234Handle<JSObject> Factory::NewNeanderObject() {
235 CALL_HEAP_FUNCTION(Heap::AllocateJSObjectFromMap(Heap::neander_map()),
236 JSObject);
237}
238
239
240Handle<Object> Factory::NewTypeError(const char* type,
241 Vector< Handle<Object> > args) {
242 return NewError("MakeTypeError", type, args);
243}
244
245
246Handle<Object> Factory::NewTypeError(Handle<String> message) {
247 return NewError("$TypeError", message);
248}
249
250
251Handle<Object> Factory::NewRangeError(const char* type,
252 Vector< Handle<Object> > args) {
253 return NewError("MakeRangeError", type, args);
254}
255
256
257Handle<Object> Factory::NewRangeError(Handle<String> message) {
258 return NewError("$RangeError", message);
259}
260
261
262Handle<Object> Factory::NewSyntaxError(const char* type, Handle<JSArray> args) {
263 return NewError("MakeSyntaxError", type, args);
264}
265
266
267Handle<Object> Factory::NewSyntaxError(Handle<String> message) {
268 return NewError("$SyntaxError", message);
269}
270
271
272Handle<Object> Factory::NewReferenceError(const char* type,
273 Vector< Handle<Object> > args) {
274 return NewError("MakeReferenceError", type, args);
275}
276
277
278Handle<Object> Factory::NewReferenceError(Handle<String> message) {
279 return NewError("$ReferenceError", message);
280}
281
282
283Handle<Object> Factory::NewError(const char* maker, const char* type,
284 Vector< Handle<Object> > args) {
285 HandleScope scope;
286 Handle<JSArray> array = NewJSArray(args.length());
287 for (int i = 0; i < args.length(); i++)
288 SetElement(array, i, args[i]);
289 Handle<Object> result = NewError(maker, type, array);
290 return result.EscapeFrom(&scope);
291}
292
293
294Handle<Object> Factory::NewEvalError(const char* type,
295 Vector< Handle<Object> > args) {
296 return NewError("MakeEvalError", type, args);
297}
298
299
300Handle<Object> Factory::NewError(const char* type,
301 Vector< Handle<Object> > args) {
302 return NewError("MakeError", type, args);
303}
304
305
306Handle<Object> Factory::NewError(const char* maker,
307 const char* type,
308 Handle<JSArray> args) {
309 Handle<String> make_str = Factory::LookupAsciiSymbol(maker);
310 Handle<JSFunction> fun =
311 Handle<JSFunction>(
312 JSFunction::cast(
313 Top::security_context_builtins()->GetProperty(*make_str)));
314 Handle<Object> type_obj = Factory::LookupAsciiSymbol(type);
315 Object** argv[2] = { type_obj.location(),
316 Handle<Object>::cast(args).location() };
317
318 // Invoke the JavaScript factory method. If an exception is thrown while
319 // running the factory method, use the exception as the result.
320 bool caught_exception;
321 Handle<Object> result = Execution::TryCall(fun,
322 Top::security_context_builtins(),
323 2,
324 argv,
325 &caught_exception);
326 return result;
327}
328
329
330Handle<Object> Factory::NewError(Handle<String> message) {
331 return NewError("$Error", message);
332}
333
334
335Handle<Object> Factory::NewError(const char* constructor,
336 Handle<String> message) {
337 Handle<String> constr = Factory::LookupAsciiSymbol(constructor);
338 Handle<JSFunction> fun =
339 Handle<JSFunction>(
340 JSFunction::cast(
341 Top::security_context_builtins()->GetProperty(*constr)));
342 Object** argv[1] = { Handle<Object>::cast(message).location() };
343
344 // Invoke the JavaScript factory method. If an exception is thrown while
345 // running the factory method, use the exception as the result.
346 bool caught_exception;
347 Handle<Object> result = Execution::TryCall(fun,
348 Top::security_context_builtins(),
349 1,
350 argv,
351 &caught_exception);
352 return result;
353}
354
355
356Handle<JSFunction> Factory::NewFunction(Handle<String> name,
357 InstanceType type,
358 int instance_size,
359 Handle<Code> code,
360 bool force_initial_map) {
361 // Allocate the function
362 Handle<JSFunction> function = NewFunction(name, the_hole_value());
363 function->set_code(*code);
364
365 if (force_initial_map ||
366 type != JS_OBJECT_TYPE ||
367 instance_size != JSObject::kHeaderSize) {
368 Handle<Map> initial_map = NewMap(type, instance_size);
369 Handle<JSObject> prototype = NewFunctionPrototype(function);
370 initial_map->set_prototype(*prototype);
371 function->set_initial_map(*initial_map);
372 initial_map->set_constructor(*function);
373 } else {
374 ASSERT(!function->has_initial_map());
375 ASSERT(!function->has_prototype());
376 }
377
378 return function;
379}
380
381
382Handle<JSFunction> Factory::NewFunctionBoilerplate(Handle<String> name,
383 int number_of_literals,
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000384 bool contains_array_literal,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000385 Handle<Code> code) {
386 Handle<JSFunction> function = NewFunctionBoilerplate(name);
387 function->set_code(*code);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000388 int literals_array_size = number_of_literals;
389 // If the function contains object, regexp or array literals,
390 // allocate extra space for a literals array prefix containing the
391 // object, regexp and array constructor functions.
392 if (number_of_literals > 0 || contains_array_literal) {
393 literals_array_size += JSFunction::kLiteralsPrefixSize;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000394 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000395 Handle<FixedArray> literals =
396 Factory::NewFixedArray(literals_array_size, TENURED);
397 function->set_literals(*literals);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000398 ASSERT(!function->has_initial_map());
399 ASSERT(!function->has_prototype());
400 return function;
401}
402
403
404Handle<JSFunction> Factory::NewFunctionBoilerplate(Handle<String> name) {
405 Handle<SharedFunctionInfo> shared = NewSharedFunctionInfo(name);
406 CALL_HEAP_FUNCTION(Heap::AllocateFunction(Heap::boilerplate_function_map(),
407 *shared,
408 Heap::the_hole_value()),
409 JSFunction);
410}
411
412
413Handle<JSFunction> Factory::NewFunctionWithPrototype(Handle<String> name,
414 InstanceType type,
415 int instance_size,
416 Handle<JSObject> prototype,
417 Handle<Code> code,
418 bool force_initial_map) {
419 // Allocate the function
420 Handle<JSFunction> function = NewFunction(name, prototype);
421
422 function->set_code(*code);
423
424 if (force_initial_map ||
425 type != JS_OBJECT_TYPE ||
426 instance_size != JSObject::kHeaderSize) {
427 Handle<Map> initial_map = NewMap(type, instance_size);
428 function->set_initial_map(*initial_map);
429 initial_map->set_constructor(*function);
430 }
431
432 // Set function.prototype and give the prototype a constructor
433 // property that refers to the function.
434 SetPrototypeProperty(function, prototype);
435 SetProperty(prototype, Factory::constructor_symbol(), function, DONT_ENUM);
436 return function;
437}
438
439Handle<Code> Factory::NewCode(const CodeDesc& desc, ScopeInfo<>* sinfo,
440 Code::Flags flags) {
441 CALL_HEAP_FUNCTION(Heap::CreateCode(desc, sinfo, flags), Code);
442}
443
444
445Handle<Code> Factory::CopyCode(Handle<Code> code) {
446 CALL_HEAP_FUNCTION(Heap::CopyCode(*code), Code);
447}
448
449
450#define CALL_GC(RETRY) \
451 do { \
452 if (!Heap::CollectGarbage(Failure::cast(RETRY)->requested(), \
453 Failure::cast(RETRY)->allocation_space())) { \
454 /* TODO(1181417): Fix this. */ \
455 V8::FatalProcessOutOfMemory("Factory CALL_GC"); \
456 } \
457 } while (false)
458
459
460// Allocate the new array. We cannot use the CALL_HEAP_FUNCTION macro here,
461// because the stack-allocated CallbacksDescriptor instance is not GC safe.
462Handle<DescriptorArray> Factory::CopyAppendProxyDescriptor(
463 Handle<DescriptorArray> array,
464 Handle<String> key,
465 Handle<Object> value,
466 PropertyAttributes attributes) {
467 GC_GREEDY_CHECK();
468 CallbacksDescriptor desc(*key, *value, attributes);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000469 Object* obj = array->CopyInsert(&desc, REMOVE_TRANSITIONS);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000470 if (obj->IsRetryAfterGC()) {
471 CALL_GC(obj);
472 CallbacksDescriptor desc(*key, *value, attributes);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000473 obj = array->CopyInsert(&desc, REMOVE_TRANSITIONS);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000474 if (obj->IsFailure()) {
475 // TODO(1181417): Fix this.
476 V8::FatalProcessOutOfMemory("CopyAppendProxyDescriptor");
477 }
478 }
479 return Handle<DescriptorArray>(DescriptorArray::cast(obj));
480}
481
482#undef CALL_GC
483
484
485Handle<String> Factory::SymbolFromString(Handle<String> value) {
486 CALL_HEAP_FUNCTION(Heap::LookupSymbol(*value), String);
487}
488
489
490Handle<DescriptorArray> Factory::CopyAppendCallbackDescriptors(
491 Handle<DescriptorArray> array,
492 Handle<Object> descriptors) {
493 v8::NeanderArray callbacks(descriptors);
494 int nof_callbacks = callbacks.length();
495 Handle<DescriptorArray> result =
496 NewDescriptorArray(array->number_of_descriptors() + nof_callbacks);
497
498 // Number of descriptors added to the result so far.
499 int descriptor_count = 0;
500
501 // Copy the descriptors from the array.
502 DescriptorWriter w(*result);
503 for (DescriptorReader r(*array); !r.eos(); r.advance()) {
504 w.WriteFrom(&r);
505 descriptor_count++;
506 }
507
508 // Number of duplicates detected.
509 int duplicates = 0;
510
511 // Fill in new callback descriptors. Process the callbacks from
512 // back to front so that the last callback with a given name takes
513 // precedence over previously added callbacks with that name.
514 for (int i = nof_callbacks - 1; i >= 0; i--) {
515 Handle<AccessorInfo> entry =
516 Handle<AccessorInfo>(AccessorInfo::cast(callbacks.get(i)));
517 // Ensure the key is a symbol before writing into the instance descriptor.
518 Handle<String> key =
519 SymbolFromString(Handle<String>(String::cast(entry->name())));
520 // Check if a descriptor with this name already exists before writing.
521 if (result->BinarySearch(*key, 0, descriptor_count - 1) ==
522 DescriptorArray::kNotFound) {
523 CallbacksDescriptor desc(*key, *entry, entry->property_attributes());
524 w.Write(&desc);
525 descriptor_count++;
526 } else {
527 duplicates++;
528 }
529 }
530
531 // If duplicates were detected, allocate a result of the right size
532 // and transfer the elements.
533 if (duplicates > 0) {
534 Handle<DescriptorArray> new_result =
535 NewDescriptorArray(result->number_of_descriptors() - duplicates);
536 DescriptorWriter w(*new_result);
537 DescriptorReader r(*result);
538 while (!w.eos()) {
539 w.WriteFrom(&r);
540 r.advance();
541 }
542 result = new_result;
543 }
544
545 // Sort the result before returning.
546 result->Sort();
547 return result;
548}
549
550
551Handle<JSObject> Factory::NewJSObject(Handle<JSFunction> constructor,
552 PretenureFlag pretenure) {
553 CALL_HEAP_FUNCTION(Heap::AllocateJSObject(*constructor, pretenure), JSObject);
554}
555
556
ager@chromium.org236ad962008-09-25 09:45:57 +0000557Handle<JSObject> Factory::NewJSObjectFromMap(Handle<Map> map) {
558 CALL_HEAP_FUNCTION(Heap::AllocateJSObjectFromMap(*map, NOT_TENURED),
559 JSObject);
560}
561
562
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000563Handle<JSObject> Factory::NewObjectLiteral(int expected_number_of_properties) {
564 Handle<Map> map = Handle<Map>(Top::object_function()->initial_map());
565 map = Factory::CopyMap(map);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000566 map->set_instance_descriptors(Heap::empty_descriptor_array());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000567 map->set_unused_property_fields(expected_number_of_properties);
568 CALL_HEAP_FUNCTION(Heap::AllocateJSObjectFromMap(*map, TENURED),
569 JSObject);
570}
571
572
573Handle<JSArray> Factory::NewArrayLiteral(int length) {
574 return NewJSArrayWithElements(NewFixedArray(length), TENURED);
575}
576
577
578Handle<JSArray> Factory::NewJSArray(int length,
579 PretenureFlag pretenure) {
580 Handle<JSObject> obj = NewJSObject(Top::array_function(), pretenure);
581 CALL_HEAP_FUNCTION(Handle<JSArray>::cast(obj)->Initialize(length), JSArray);
582}
583
584
585Handle<JSArray> Factory::NewJSArrayWithElements(Handle<FixedArray> elements,
586 PretenureFlag pretenure) {
587 Handle<JSArray> result =
588 Handle<JSArray>::cast(NewJSObject(Top::array_function(), pretenure));
589 result->SetContent(*elements);
590 return result;
591}
592
593
594Handle<SharedFunctionInfo> Factory::NewSharedFunctionInfo(Handle<String> name) {
595 CALL_HEAP_FUNCTION(Heap::AllocateSharedFunctionInfo(*name),
596 SharedFunctionInfo);
597}
598
599
600Handle<Dictionary> Factory::DictionaryAtNumberPut(Handle<Dictionary> dictionary,
601 uint32_t key,
602 Handle<Object> value) {
603 CALL_HEAP_FUNCTION(dictionary->AtNumberPut(key, *value), Dictionary);
604}
605
606
607Handle<JSFunction> Factory::NewFunctionHelper(Handle<String> name,
608 Handle<Object> prototype) {
609 Handle<SharedFunctionInfo> function_share = NewSharedFunctionInfo(name);
610 CALL_HEAP_FUNCTION(Heap::AllocateFunction(*Top::function_map(),
611 *function_share,
612 *prototype),
613 JSFunction);
614}
615
616
617Handle<JSFunction> Factory::NewFunction(Handle<String> name,
618 Handle<Object> prototype) {
619 Handle<JSFunction> fun = NewFunctionHelper(name, prototype);
620 fun->set_context(Top::context()->global_context());
621 return fun;
622}
623
624
625Handle<Object> Factory::ToObject(Handle<Object> object,
626 Handle<Context> global_context) {
627 CALL_HEAP_FUNCTION(object->ToObject(*global_context), Object);
628}
629
630
v8.team.kasperl727e9952008-09-02 14:56:44 +0000631Handle<DebugInfo> Factory::NewDebugInfo(Handle<SharedFunctionInfo> shared) {
632 // Get the original code of the function.
633 Handle<Code> code(shared->code());
634
635 // Create a copy of the code before allocating the debug info object to avoid
636 // allocation while setting up the debug info object.
637 Handle<Code> original_code(*Factory::CopyCode(code));
638
639 // Allocate initial fixed array for active break points before allocating the
640 // debug info object to avoid allocation while setting up the debug info
641 // object.
642 Handle<FixedArray> break_points(
643 Factory::NewFixedArray(Debug::kEstimatedNofBreakPointsInFunction));
644
645 // Create and set up the debug info object. Debug info contains function, a
646 // copy of the original code, the executing code and initial fixed array for
647 // active break points.
648 Handle<DebugInfo> debug_info =
649 Handle<DebugInfo>::cast(Factory::NewStruct(DEBUG_INFO_TYPE));
650 debug_info->set_shared(*shared);
651 debug_info->set_original_code(*original_code);
652 debug_info->set_code(*code);
653 debug_info->set_break_points(*break_points);
654
655 // Link debug info to function.
656 shared->set_debug_info(*debug_info);
657
658 return debug_info;
659}
660
661
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000662Handle<JSObject> Factory::NewArgumentsObject(Handle<Object> callee,
663 int length) {
664 CALL_HEAP_FUNCTION(Heap::AllocateArgumentsObject(*callee, length), JSObject);
665}
666
667
668Handle<JSFunction> Factory::CreateApiFunction(
669 Handle<FunctionTemplateInfo> obj,
670 bool is_global) {
671 Handle<Code> code = Handle<Code>(Builtins::builtin(Builtins::HandleApiCall));
672
kasper.lund212ac232008-07-16 07:07:30 +0000673 int internal_field_count = 0;
674 if (!obj->instance_template()->IsUndefined()) {
675 Handle<ObjectTemplateInfo> instance_template =
676 Handle<ObjectTemplateInfo>(
677 ObjectTemplateInfo::cast(obj->instance_template()));
678 internal_field_count =
679 Smi::cast(instance_template->internal_field_count())->value();
680 }
681
682 int instance_size = kPointerSize * internal_field_count;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000683 if (is_global) {
kasper.lund212ac232008-07-16 07:07:30 +0000684 instance_size += JSGlobalObject::kSize;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000685 } else {
kasper.lund212ac232008-07-16 07:07:30 +0000686 instance_size += JSObject::kHeaderSize;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000687 }
688
689 InstanceType type = is_global ? JS_GLOBAL_OBJECT_TYPE : JS_OBJECT_TYPE;
690
691 Handle<JSFunction> result =
kasper.lund212ac232008-07-16 07:07:30 +0000692 Factory::NewFunction(Factory::empty_symbol(), type, instance_size,
693 code, true);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000694 // Set class name.
695 Handle<Object> class_name = Handle<Object>(obj->class_name());
696 if (class_name->IsString()) {
697 result->shared()->set_instance_class_name(*class_name);
698 result->shared()->set_name(*class_name);
699 }
700
701 Handle<Map> map = Handle<Map>(result->initial_map());
702
703 // Mark as undetectable if needed.
704 if (obj->undetectable()) {
705 map->set_is_undetectable();
706 }
707
708 // Mark as hidden for the __proto__ accessor if needed.
709 if (obj->hidden_prototype()) {
710 map->set_is_hidden_prototype();
711 }
712
713 // Mark as needs_access_check if needed.
714 if (obj->needs_access_check()) {
715 map->set_needs_access_check();
716 }
717
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000718 // Set interceptor information in the map.
719 if (!obj->named_property_handler()->IsUndefined()) {
720 map->set_has_named_interceptor();
721 }
722 if (!obj->indexed_property_handler()->IsUndefined()) {
723 map->set_has_indexed_interceptor();
724 }
725
726 // Set instance call-as-function information in the map.
727 if (!obj->instance_call_handler()->IsUndefined()) {
728 map->set_has_instance_call_handler();
729 }
730
731 result->shared()->set_function_data(*obj);
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000732 result->shared()->DontAdaptArguments();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000733
734 // Recursively copy parent templates' accessors, 'data' may be modified.
735 Handle<DescriptorArray> array =
736 Handle<DescriptorArray>(map->instance_descriptors());
737 while (true) {
738 Handle<Object> props = Handle<Object>(obj->property_accessors());
739 if (!props->IsUndefined()) {
740 array = Factory::CopyAppendCallbackDescriptors(array, props);
741 }
742 Handle<Object> parent = Handle<Object>(obj->parent_template());
743 if (parent->IsUndefined()) break;
744 obj = Handle<FunctionTemplateInfo>::cast(parent);
745 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000746 if (!array->IsEmpty()) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000747 map->set_instance_descriptors(*array);
748 }
749
750 return result;
751}
752
753
ager@chromium.org236ad962008-09-25 09:45:57 +0000754Handle<MapCache> Factory::NewMapCache(int at_least_space_for) {
755 CALL_HEAP_FUNCTION(MapCache::Allocate(at_least_space_for), MapCache);
756}
757
758
759static Object* UpdateMapCacheWith(Context* context,
760 FixedArray* keys,
761 Map* map) {
762 Object* result = MapCache::cast(context->map_cache())->Put(keys, map);
763 if (!result->IsFailure()) context->set_map_cache(MapCache::cast(result));
764 return result;
765}
766
767
768Handle<MapCache> Factory::AddToMapCache(Handle<Context> context,
769 Handle<FixedArray> keys,
770 Handle<Map> map) {
771 CALL_HEAP_FUNCTION(UpdateMapCacheWith(*context, *keys, *map), MapCache);
772}
773
774
775Handle<Map> Factory::ObjectLiteralMapFromCache(Handle<Context> context,
776 Handle<FixedArray> keys) {
777 if (context->map_cache()->IsUndefined()) {
778 // Allocate the new map cache for the global context.
779 Handle<MapCache> new_cache = NewMapCache(24);
780 context->set_map_cache(*new_cache);
781 }
782 // Check to see whether there is a maching element in the cache.
783 Handle<MapCache> cache =
784 Handle<MapCache>(MapCache::cast(context->map_cache()));
785 Handle<Object> result = Handle<Object>(cache->Lookup(*keys));
786 if (result->IsMap()) return Handle<Map>::cast(result);
787 // Create a new map and add it to the cache.
788 Handle<Map> map =
789 CopyMap(Handle<Map>(context->object_function()->initial_map()));
790 AddToMapCache(context, keys, map);
791 return Handle<Map>(map);
792}
793
794
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000795void Factory::ConfigureInstance(Handle<FunctionTemplateInfo> desc,
796 Handle<JSObject> instance,
797 bool* pending_exception) {
798 // Configure the instance by adding the properties specified by the
799 // instance template.
800 Handle<Object> instance_template = Handle<Object>(desc->instance_template());
801 if (!instance_template->IsUndefined()) {
802 Execution::ConfigureInstance(instance,
803 instance_template,
804 pending_exception);
805 } else {
806 *pending_exception = false;
807 }
808}
809
810
811} } // namespace v8::internal