blob: 20f82612d2be4d925eced6276d4679ab389092c4 [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
kasperl@chromium.org71affb52009-05-26 05:44:31 +000036namespace v8 {
37namespace internal {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000038
39
40Handle<FixedArray> Factory::NewFixedArray(int size, PretenureFlag pretenure) {
41 ASSERT(0 <= size);
42 CALL_HEAP_FUNCTION(Heap::AllocateFixedArray(size, pretenure), FixedArray);
43}
44
45
ricow@chromium.orgc9c80822010-04-21 08:22:37 +000046Handle<FixedArray> Factory::NewFixedArrayWithHoles(int size,
47 PretenureFlag pretenure) {
kasperl@chromium.org9bbf9682008-10-30 11:53:07 +000048 ASSERT(0 <= size);
ricow@chromium.orgc9c80822010-04-21 08:22:37 +000049 CALL_HEAP_FUNCTION(Heap::AllocateFixedArrayWithHoles(size, pretenure),
50 FixedArray);
kasperl@chromium.org9bbf9682008-10-30 11:53:07 +000051}
52
53
kasperl@chromium.org86f77b72009-07-06 08:21:57 +000054Handle<StringDictionary> Factory::NewStringDictionary(int at_least_space_for) {
kasperl@chromium.org9bbf9682008-10-30 11:53:07 +000055 ASSERT(0 <= at_least_space_for);
kasperl@chromium.org86f77b72009-07-06 08:21:57 +000056 CALL_HEAP_FUNCTION(StringDictionary::Allocate(at_least_space_for),
57 StringDictionary);
58}
59
60
61Handle<NumberDictionary> Factory::NewNumberDictionary(int at_least_space_for) {
62 ASSERT(0 <= at_least_space_for);
63 CALL_HEAP_FUNCTION(NumberDictionary::Allocate(at_least_space_for),
64 NumberDictionary);
kasperl@chromium.org9bbf9682008-10-30 11:53:07 +000065}
66
67
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000068Handle<DescriptorArray> Factory::NewDescriptorArray(int number_of_descriptors) {
69 ASSERT(0 <= number_of_descriptors);
70 CALL_HEAP_FUNCTION(DescriptorArray::Allocate(number_of_descriptors),
71 DescriptorArray);
72}
73
74
ager@chromium.org9258b6b2008-09-11 09:11:10 +000075// Symbols are created in the old generation (data space).
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000076Handle<String> Factory::LookupSymbol(Vector<const char> string) {
77 CALL_HEAP_FUNCTION(Heap::LookupSymbol(string), String);
78}
79
80
81Handle<String> Factory::NewStringFromAscii(Vector<const char> string,
82 PretenureFlag pretenure) {
83 CALL_HEAP_FUNCTION(Heap::AllocateStringFromAscii(string, pretenure), String);
84}
85
86Handle<String> Factory::NewStringFromUtf8(Vector<const char> string,
87 PretenureFlag pretenure) {
88 CALL_HEAP_FUNCTION(Heap::AllocateStringFromUtf8(string, pretenure), String);
89}
90
91
sgjesse@chromium.org911335c2009-08-19 12:59:44 +000092Handle<String> Factory::NewStringFromTwoByte(Vector<const uc16> string,
93 PretenureFlag pretenure) {
94 CALL_HEAP_FUNCTION(Heap::AllocateStringFromTwoByte(string, pretenure),
95 String);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000096}
97
98
99Handle<String> Factory::NewRawTwoByteString(int length,
100 PretenureFlag pretenure) {
101 CALL_HEAP_FUNCTION(Heap::AllocateRawTwoByteString(length, pretenure), String);
102}
103
104
105Handle<String> Factory::NewConsString(Handle<String> first,
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000106 Handle<String> second) {
ager@chromium.orgc3e50d82008-11-05 11:53:10 +0000107 CALL_HEAP_FUNCTION(Heap::AllocateConsString(*first, *second), String);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000108}
109
110
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000111Handle<String> Factory::NewSubString(Handle<String> str,
112 int begin,
113 int end) {
114 CALL_HEAP_FUNCTION(str->SubString(begin, end), String);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000115}
116
117
118Handle<String> Factory::NewExternalStringFromAscii(
119 ExternalAsciiString::Resource* resource) {
120 CALL_HEAP_FUNCTION(Heap::AllocateExternalStringFromAscii(resource), String);
121}
122
123
124Handle<String> Factory::NewExternalStringFromTwoByte(
125 ExternalTwoByteString::Resource* resource) {
126 CALL_HEAP_FUNCTION(Heap::AllocateExternalStringFromTwoByte(resource), String);
127}
128
129
130Handle<Context> Factory::NewGlobalContext() {
131 CALL_HEAP_FUNCTION(Heap::AllocateGlobalContext(), Context);
132}
133
134
135Handle<Context> Factory::NewFunctionContext(int length,
136 Handle<JSFunction> closure) {
137 CALL_HEAP_FUNCTION(Heap::AllocateFunctionContext(length, *closure), Context);
138}
139
140
141Handle<Context> Factory::NewWithContext(Handle<Context> previous,
christian.plesner.hansen@gmail.com37abdec2009-01-06 14:43:28 +0000142 Handle<JSObject> extension,
143 bool is_catch_context) {
144 CALL_HEAP_FUNCTION(Heap::AllocateWithContext(*previous,
145 *extension,
146 is_catch_context),
147 Context);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000148}
149
150
151Handle<Struct> Factory::NewStruct(InstanceType type) {
152 CALL_HEAP_FUNCTION(Heap::AllocateStruct(type), Struct);
153}
154
155
156Handle<AccessorInfo> Factory::NewAccessorInfo() {
157 Handle<AccessorInfo> info =
158 Handle<AccessorInfo>::cast(NewStruct(ACCESSOR_INFO_TYPE));
159 info->set_flag(0); // Must clear the flag, it was initialized as undefined.
160 return info;
161}
162
163
164Handle<Script> Factory::NewScript(Handle<String> source) {
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000165 // Generate id for this script.
166 int id;
167 if (Heap::last_script_id()->IsUndefined()) {
168 // Script ids start from one.
169 id = 1;
170 } else {
171 // Increment id, wrap when positive smi is exhausted.
172 id = Smi::cast(Heap::last_script_id())->value();
173 id++;
174 if (!Smi::IsValid(id)) {
175 id = 0;
176 }
177 }
178 Heap::SetLastScriptId(Smi::FromInt(id));
179
180 // Create and initialize script object.
ager@chromium.org9085a012009-05-11 19:22:57 +0000181 Handle<Proxy> wrapper = Factory::NewProxy(0, TENURED);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000182 Handle<Script> script = Handle<Script>::cast(NewStruct(SCRIPT_TYPE));
183 script->set_source(*source);
184 script->set_name(Heap::undefined_value());
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000185 script->set_id(Heap::last_script_id());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000186 script->set_line_offset(Smi::FromInt(0));
187 script->set_column_offset(Smi::FromInt(0));
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000188 script->set_data(Heap::undefined_value());
ager@chromium.org9085a012009-05-11 19:22:57 +0000189 script->set_context_data(Heap::undefined_value());
ager@chromium.orge2902be2009-06-08 12:21:35 +0000190 script->set_type(Smi::FromInt(Script::TYPE_NORMAL));
191 script->set_compilation_type(Smi::FromInt(Script::COMPILATION_TYPE_HOST));
ager@chromium.org9085a012009-05-11 19:22:57 +0000192 script->set_wrapper(*wrapper);
sgjesse@chromium.org499aaa52009-11-30 08:07:20 +0000193 script->set_line_ends(Heap::undefined_value());
sgjesse@chromium.org98180592009-12-02 08:17:28 +0000194 script->set_eval_from_shared(Heap::undefined_value());
ager@chromium.orge2902be2009-06-08 12:21:35 +0000195 script->set_eval_from_instructions_offset(Smi::FromInt(0));
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000196
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000197 return script;
198}
199
200
201Handle<Proxy> Factory::NewProxy(Address addr, PretenureFlag pretenure) {
202 CALL_HEAP_FUNCTION(Heap::AllocateProxy(addr, pretenure), Proxy);
203}
204
205
206Handle<Proxy> Factory::NewProxy(const AccessorDescriptor* desc) {
207 return NewProxy((Address) desc, TENURED);
208}
209
210
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000211Handle<ByteArray> Factory::NewByteArray(int length, PretenureFlag pretenure) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000212 ASSERT(0 <= length);
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000213 CALL_HEAP_FUNCTION(Heap::AllocateByteArray(length, pretenure), ByteArray);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000214}
215
216
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +0000217Handle<PixelArray> Factory::NewPixelArray(int length,
218 uint8_t* external_pointer,
219 PretenureFlag pretenure) {
220 ASSERT(0 <= length);
221 CALL_HEAP_FUNCTION(Heap::AllocatePixelArray(length,
222 external_pointer,
223 pretenure), PixelArray);
224}
225
226
ager@chromium.org3811b432009-10-28 14:53:37 +0000227Handle<ExternalArray> Factory::NewExternalArray(int length,
228 ExternalArrayType array_type,
229 void* external_pointer,
230 PretenureFlag pretenure) {
231 ASSERT(0 <= length);
232 CALL_HEAP_FUNCTION(Heap::AllocateExternalArray(length,
233 array_type,
234 external_pointer,
235 pretenure), ExternalArray);
236}
237
238
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000239Handle<Map> Factory::NewMap(InstanceType type, int instance_size) {
240 CALL_HEAP_FUNCTION(Heap::AllocateMap(type, instance_size), Map);
241}
242
243
244Handle<JSObject> Factory::NewFunctionPrototype(Handle<JSFunction> function) {
245 CALL_HEAP_FUNCTION(Heap::AllocateFunctionPrototype(*function), JSObject);
246}
247
248
ager@chromium.org3a37e9b2009-04-27 09:26:21 +0000249Handle<Map> Factory::CopyMapDropDescriptors(Handle<Map> src) {
250 CALL_HEAP_FUNCTION(src->CopyDropDescriptors(), Map);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000251}
252
253
ager@chromium.org32912102009-01-16 10:38:43 +0000254Handle<Map> Factory::CopyMap(Handle<Map> src,
255 int extra_inobject_properties) {
ager@chromium.org3a37e9b2009-04-27 09:26:21 +0000256 Handle<Map> copy = CopyMapDropDescriptors(src);
ager@chromium.org32912102009-01-16 10:38:43 +0000257 // Check that we do not overflow the instance size when adding the
258 // extra inobject properties.
259 int instance_size_delta = extra_inobject_properties * kPointerSize;
260 int max_instance_size_delta =
261 JSObject::kMaxInstanceSize - copy->instance_size();
262 if (instance_size_delta > max_instance_size_delta) {
263 // If the instance size overflows, we allocate as many properties
264 // as we can as inobject properties.
265 instance_size_delta = max_instance_size_delta;
266 extra_inobject_properties = max_instance_size_delta >> kPointerSizeLog2;
267 }
268 // Adjust the map with the extra inobject properties.
269 int inobject_properties =
270 copy->inobject_properties() + extra_inobject_properties;
271 copy->set_inobject_properties(inobject_properties);
272 copy->set_unused_property_fields(inobject_properties);
273 copy->set_instance_size(copy->instance_size() + instance_size_delta);
274 return copy;
275}
276
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000277Handle<Map> Factory::CopyMapDropTransitions(Handle<Map> src) {
278 CALL_HEAP_FUNCTION(src->CopyDropTransitions(), Map);
279}
280
281
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000282Handle<FixedArray> Factory::CopyFixedArray(Handle<FixedArray> array) {
283 CALL_HEAP_FUNCTION(array->Copy(), FixedArray);
284}
285
286
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +0000287Handle<JSFunction> Factory::BaseNewFunctionFromSharedFunctionInfo(
288 Handle<SharedFunctionInfo> function_info,
sgjesse@chromium.org846fb742009-12-18 08:56:33 +0000289 Handle<Map> function_map,
290 PretenureFlag pretenure) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000291 CALL_HEAP_FUNCTION(Heap::AllocateFunction(*function_map,
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +0000292 *function_info,
sgjesse@chromium.org846fb742009-12-18 08:56:33 +0000293 Heap::the_hole_value(),
294 pretenure),
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000295 JSFunction);
296}
297
298
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +0000299Handle<JSFunction> Factory::NewFunctionFromSharedFunctionInfo(
300 Handle<SharedFunctionInfo> function_info,
sgjesse@chromium.org846fb742009-12-18 08:56:33 +0000301 Handle<Context> context,
302 PretenureFlag pretenure) {
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +0000303 Handle<JSFunction> result = BaseNewFunctionFromSharedFunctionInfo(
304 function_info, Top::function_map(), pretenure);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000305 result->set_context(*context);
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +0000306 int number_of_literals = function_info->num_literals();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000307 Handle<FixedArray> literals =
sgjesse@chromium.org846fb742009-12-18 08:56:33 +0000308 Factory::NewFixedArray(number_of_literals, pretenure);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000309 if (number_of_literals > 0) {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000310 // Store the object, regexp and array functions in the literals
311 // array prefix. These functions will be used when creating
312 // object, regexp and array literals in this function.
ager@chromium.org236ad962008-09-25 09:45:57 +0000313 literals->set(JSFunction::kLiteralGlobalContextIndex,
314 context->global_context());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000315 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000316 result->set_literals(*literals);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000317 return result;
318}
319
320
321Handle<Object> Factory::NewNumber(double value,
322 PretenureFlag pretenure) {
323 CALL_HEAP_FUNCTION(Heap::NumberFromDouble(value, pretenure), Object);
324}
325
326
327Handle<Object> Factory::NewNumberFromInt(int value) {
328 CALL_HEAP_FUNCTION(Heap::NumberFromInt32(value), Object);
329}
330
331
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000332Handle<Object> Factory::NewNumberFromUint(uint32_t value) {
333 CALL_HEAP_FUNCTION(Heap::NumberFromUint32(value), Object);
334}
335
336
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000337Handle<JSObject> Factory::NewNeanderObject() {
338 CALL_HEAP_FUNCTION(Heap::AllocateJSObjectFromMap(Heap::neander_map()),
339 JSObject);
340}
341
342
343Handle<Object> Factory::NewTypeError(const char* type,
344 Vector< Handle<Object> > args) {
345 return NewError("MakeTypeError", type, args);
346}
347
348
349Handle<Object> Factory::NewTypeError(Handle<String> message) {
350 return NewError("$TypeError", message);
351}
352
353
354Handle<Object> Factory::NewRangeError(const char* type,
355 Vector< Handle<Object> > args) {
356 return NewError("MakeRangeError", type, args);
357}
358
359
360Handle<Object> Factory::NewRangeError(Handle<String> message) {
361 return NewError("$RangeError", message);
362}
363
364
365Handle<Object> Factory::NewSyntaxError(const char* type, Handle<JSArray> args) {
366 return NewError("MakeSyntaxError", type, args);
367}
368
369
370Handle<Object> Factory::NewSyntaxError(Handle<String> message) {
371 return NewError("$SyntaxError", message);
372}
373
374
375Handle<Object> Factory::NewReferenceError(const char* type,
376 Vector< Handle<Object> > args) {
377 return NewError("MakeReferenceError", type, args);
378}
379
380
381Handle<Object> Factory::NewReferenceError(Handle<String> message) {
382 return NewError("$ReferenceError", message);
383}
384
385
386Handle<Object> Factory::NewError(const char* maker, const char* type,
387 Vector< Handle<Object> > args) {
ager@chromium.orgddb913d2009-01-27 10:01:48 +0000388 v8::HandleScope scope; // Instantiate a closeable HandleScope for EscapeFrom.
ager@chromium.org7c537e22008-10-16 08:43:32 +0000389 Handle<FixedArray> array = Factory::NewFixedArray(args.length());
390 for (int i = 0; i < args.length(); i++) {
391 array->set(i, *args[i]);
392 }
393 Handle<JSArray> object = Factory::NewJSArrayWithElements(array);
394 Handle<Object> result = NewError(maker, type, object);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000395 return result.EscapeFrom(&scope);
396}
397
398
399Handle<Object> Factory::NewEvalError(const char* type,
400 Vector< Handle<Object> > args) {
401 return NewError("MakeEvalError", type, args);
402}
403
404
405Handle<Object> Factory::NewError(const char* type,
406 Vector< Handle<Object> > args) {
407 return NewError("MakeError", type, args);
408}
409
410
411Handle<Object> Factory::NewError(const char* maker,
412 const char* type,
413 Handle<JSArray> args) {
414 Handle<String> make_str = Factory::LookupAsciiSymbol(maker);
ager@chromium.org4af710e2009-09-15 12:20:11 +0000415 Handle<Object> fun_obj(Top::builtins()->GetProperty(*make_str));
416 // If the builtins haven't been properly configured yet this error
417 // constructor may not have been defined. Bail out.
418 if (!fun_obj->IsJSFunction())
419 return Factory::undefined_value();
420 Handle<JSFunction> fun = Handle<JSFunction>::cast(fun_obj);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000421 Handle<Object> type_obj = Factory::LookupAsciiSymbol(type);
422 Object** argv[2] = { type_obj.location(),
423 Handle<Object>::cast(args).location() };
424
425 // Invoke the JavaScript factory method. If an exception is thrown while
426 // running the factory method, use the exception as the result.
427 bool caught_exception;
428 Handle<Object> result = Execution::TryCall(fun,
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000429 Top::builtins(),
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000430 2,
431 argv,
432 &caught_exception);
433 return result;
434}
435
436
437Handle<Object> Factory::NewError(Handle<String> message) {
438 return NewError("$Error", message);
439}
440
441
442Handle<Object> Factory::NewError(const char* constructor,
443 Handle<String> message) {
444 Handle<String> constr = Factory::LookupAsciiSymbol(constructor);
445 Handle<JSFunction> fun =
446 Handle<JSFunction>(
447 JSFunction::cast(
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000448 Top::builtins()->GetProperty(*constr)));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000449 Object** argv[1] = { Handle<Object>::cast(message).location() };
450
451 // Invoke the JavaScript factory method. If an exception is thrown while
452 // running the factory method, use the exception as the result.
453 bool caught_exception;
454 Handle<Object> result = Execution::TryCall(fun,
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000455 Top::builtins(),
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000456 1,
457 argv,
458 &caught_exception);
459 return result;
460}
461
462
463Handle<JSFunction> Factory::NewFunction(Handle<String> name,
464 InstanceType type,
465 int instance_size,
466 Handle<Code> code,
467 bool force_initial_map) {
468 // Allocate the function
469 Handle<JSFunction> function = NewFunction(name, the_hole_value());
470 function->set_code(*code);
471
472 if (force_initial_map ||
473 type != JS_OBJECT_TYPE ||
474 instance_size != JSObject::kHeaderSize) {
475 Handle<Map> initial_map = NewMap(type, instance_size);
476 Handle<JSObject> prototype = NewFunctionPrototype(function);
477 initial_map->set_prototype(*prototype);
478 function->set_initial_map(*initial_map);
479 initial_map->set_constructor(*function);
480 } else {
481 ASSERT(!function->has_initial_map());
482 ASSERT(!function->has_prototype());
483 }
484
485 return function;
486}
487
488
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000489Handle<JSFunction> Factory::NewFunctionWithPrototype(Handle<String> name,
490 InstanceType type,
491 int instance_size,
492 Handle<JSObject> prototype,
493 Handle<Code> code,
494 bool force_initial_map) {
495 // Allocate the function
496 Handle<JSFunction> function = NewFunction(name, prototype);
497
498 function->set_code(*code);
499
500 if (force_initial_map ||
501 type != JS_OBJECT_TYPE ||
502 instance_size != JSObject::kHeaderSize) {
503 Handle<Map> initial_map = NewMap(type, instance_size);
504 function->set_initial_map(*initial_map);
505 initial_map->set_constructor(*function);
506 }
507
508 // Set function.prototype and give the prototype a constructor
509 // property that refers to the function.
510 SetPrototypeProperty(function, prototype);
511 SetProperty(prototype, Factory::constructor_symbol(), function, DONT_ENUM);
512 return function;
513}
514
kasperl@chromium.org9bbf9682008-10-30 11:53:07 +0000515
kasperl@chromium.org71affb52009-05-26 05:44:31 +0000516Handle<Code> Factory::NewCode(const CodeDesc& desc,
517 ZoneScopeInfo* sinfo,
518 Code::Flags flags,
519 Handle<Object> self_ref) {
kasperl@chromium.org061ef742009-02-27 12:16:20 +0000520 CALL_HEAP_FUNCTION(Heap::CreateCode(desc, sinfo, flags, self_ref), Code);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000521}
522
523
524Handle<Code> Factory::CopyCode(Handle<Code> code) {
525 CALL_HEAP_FUNCTION(Heap::CopyCode(*code), Code);
526}
527
528
fschneider@chromium.org086aac62010-03-17 13:18:24 +0000529Handle<Code> Factory::CopyCode(Handle<Code> code, Vector<byte> reloc_info) {
530 CALL_HEAP_FUNCTION(Heap::CopyCode(*code, reloc_info), Code);
531}
532
533
kasperl@chromium.org9bbf9682008-10-30 11:53:07 +0000534static inline Object* DoCopyInsert(DescriptorArray* array,
535 String* key,
536 Object* value,
537 PropertyAttributes attributes) {
538 CallbacksDescriptor desc(key, value, attributes);
539 Object* obj = array->CopyInsert(&desc, REMOVE_TRANSITIONS);
540 return obj;
541}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000542
543
kasperl@chromium.org9bbf9682008-10-30 11:53:07 +0000544// Allocate the new array.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000545Handle<DescriptorArray> Factory::CopyAppendProxyDescriptor(
546 Handle<DescriptorArray> array,
547 Handle<String> key,
548 Handle<Object> value,
549 PropertyAttributes attributes) {
kasperl@chromium.org9bbf9682008-10-30 11:53:07 +0000550 CALL_HEAP_FUNCTION(DoCopyInsert(*array, *key, *value, attributes),
551 DescriptorArray);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000552}
553
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000554
555Handle<String> Factory::SymbolFromString(Handle<String> value) {
556 CALL_HEAP_FUNCTION(Heap::LookupSymbol(*value), String);
557}
558
559
560Handle<DescriptorArray> Factory::CopyAppendCallbackDescriptors(
561 Handle<DescriptorArray> array,
562 Handle<Object> descriptors) {
563 v8::NeanderArray callbacks(descriptors);
564 int nof_callbacks = callbacks.length();
565 Handle<DescriptorArray> result =
566 NewDescriptorArray(array->number_of_descriptors() + nof_callbacks);
567
568 // Number of descriptors added to the result so far.
569 int descriptor_count = 0;
570
571 // Copy the descriptors from the array.
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +0000572 for (int i = 0; i < array->number_of_descriptors(); i++) {
573 if (array->GetType(i) != NULL_DESCRIPTOR) {
574 result->CopyFrom(descriptor_count++, *array, i);
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000575 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000576 }
577
578 // Number of duplicates detected.
579 int duplicates = 0;
580
581 // Fill in new callback descriptors. Process the callbacks from
582 // back to front so that the last callback with a given name takes
583 // precedence over previously added callbacks with that name.
584 for (int i = nof_callbacks - 1; i >= 0; i--) {
585 Handle<AccessorInfo> entry =
586 Handle<AccessorInfo>(AccessorInfo::cast(callbacks.get(i)));
587 // Ensure the key is a symbol before writing into the instance descriptor.
588 Handle<String> key =
589 SymbolFromString(Handle<String>(String::cast(entry->name())));
590 // Check if a descriptor with this name already exists before writing.
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000591 if (result->LinearSearch(*key, descriptor_count) ==
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000592 DescriptorArray::kNotFound) {
593 CallbacksDescriptor desc(*key, *entry, entry->property_attributes());
kasperl@chromium.org68ac0092009-07-09 06:00:35 +0000594 result->Set(descriptor_count, &desc);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000595 descriptor_count++;
596 } else {
597 duplicates++;
598 }
599 }
600
601 // If duplicates were detected, allocate a result of the right size
602 // and transfer the elements.
603 if (duplicates > 0) {
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +0000604 int number_of_descriptors = result->number_of_descriptors() - duplicates;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000605 Handle<DescriptorArray> new_result =
kasperl@chromium.orgdefbd102009-07-13 14:04:26 +0000606 NewDescriptorArray(number_of_descriptors);
607 for (int i = 0; i < number_of_descriptors; i++) {
608 new_result->CopyFrom(i, *result, i);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000609 }
610 result = new_result;
611 }
612
613 // Sort the result before returning.
614 result->Sort();
615 return result;
616}
617
618
619Handle<JSObject> Factory::NewJSObject(Handle<JSFunction> constructor,
620 PretenureFlag pretenure) {
621 CALL_HEAP_FUNCTION(Heap::AllocateJSObject(*constructor, pretenure), JSObject);
622}
623
624
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000625Handle<GlobalObject> Factory::NewGlobalObject(
626 Handle<JSFunction> constructor) {
627 CALL_HEAP_FUNCTION(Heap::AllocateGlobalObject(*constructor),
628 GlobalObject);
629}
630
631
632
ager@chromium.org236ad962008-09-25 09:45:57 +0000633Handle<JSObject> Factory::NewJSObjectFromMap(Handle<Map> map) {
634 CALL_HEAP_FUNCTION(Heap::AllocateJSObjectFromMap(*map, NOT_TENURED),
635 JSObject);
636}
637
638
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000639Handle<JSArray> Factory::NewJSArray(int length,
640 PretenureFlag pretenure) {
641 Handle<JSObject> obj = NewJSObject(Top::array_function(), pretenure);
642 CALL_HEAP_FUNCTION(Handle<JSArray>::cast(obj)->Initialize(length), JSArray);
643}
644
645
646Handle<JSArray> Factory::NewJSArrayWithElements(Handle<FixedArray> elements,
647 PretenureFlag pretenure) {
648 Handle<JSArray> result =
649 Handle<JSArray>::cast(NewJSObject(Top::array_function(), pretenure));
650 result->SetContent(*elements);
651 return result;
652}
653
654
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +0000655Handle<SharedFunctionInfo> Factory::NewSharedFunctionInfo(
656 Handle<String> name, int number_of_literals, Handle<Code> code) {
657 Handle<SharedFunctionInfo> shared = NewSharedFunctionInfo(name);
658 shared->set_code(*code);
659 int literals_array_size = number_of_literals;
660 // If the function contains object, regexp or array literals,
661 // allocate extra space for a literals array prefix containing the
662 // context.
663 if (number_of_literals > 0) {
664 literals_array_size += JSFunction::kLiteralsPrefixSize;
665 }
666 shared->set_num_literals(literals_array_size);
667 return shared;
668}
669
670
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000671Handle<SharedFunctionInfo> Factory::NewSharedFunctionInfo(Handle<String> name) {
672 CALL_HEAP_FUNCTION(Heap::AllocateSharedFunctionInfo(*name),
673 SharedFunctionInfo);
674}
675
676
sgjesse@chromium.orgc5145742009-10-07 09:00:33 +0000677Handle<String> Factory::NumberToString(Handle<Object> number) {
678 CALL_HEAP_FUNCTION(Heap::NumberToString(*number), String);
679}
680
681
kasperl@chromium.org86f77b72009-07-06 08:21:57 +0000682Handle<NumberDictionary> Factory::DictionaryAtNumberPut(
683 Handle<NumberDictionary> dictionary,
684 uint32_t key,
685 Handle<Object> value) {
686 CALL_HEAP_FUNCTION(dictionary->AtNumberPut(key, *value), NumberDictionary);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000687}
688
689
690Handle<JSFunction> Factory::NewFunctionHelper(Handle<String> name,
691 Handle<Object> prototype) {
692 Handle<SharedFunctionInfo> function_share = NewSharedFunctionInfo(name);
693 CALL_HEAP_FUNCTION(Heap::AllocateFunction(*Top::function_map(),
694 *function_share,
695 *prototype),
696 JSFunction);
697}
698
699
700Handle<JSFunction> Factory::NewFunction(Handle<String> name,
701 Handle<Object> prototype) {
702 Handle<JSFunction> fun = NewFunctionHelper(name, prototype);
703 fun->set_context(Top::context()->global_context());
704 return fun;
705}
706
707
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000708Handle<Object> Factory::ToObject(Handle<Object> object) {
709 CALL_HEAP_FUNCTION(object->ToObject(), Object);
710}
711
712
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000713Handle<Object> Factory::ToObject(Handle<Object> object,
714 Handle<Context> global_context) {
715 CALL_HEAP_FUNCTION(object->ToObject(*global_context), Object);
716}
717
718
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000719#ifdef ENABLE_DEBUGGER_SUPPORT
v8.team.kasperl727e9952008-09-02 14:56:44 +0000720Handle<DebugInfo> Factory::NewDebugInfo(Handle<SharedFunctionInfo> shared) {
721 // Get the original code of the function.
722 Handle<Code> code(shared->code());
723
724 // Create a copy of the code before allocating the debug info object to avoid
725 // allocation while setting up the debug info object.
726 Handle<Code> original_code(*Factory::CopyCode(code));
727
728 // Allocate initial fixed array for active break points before allocating the
729 // debug info object to avoid allocation while setting up the debug info
730 // object.
731 Handle<FixedArray> break_points(
732 Factory::NewFixedArray(Debug::kEstimatedNofBreakPointsInFunction));
733
734 // Create and set up the debug info object. Debug info contains function, a
735 // copy of the original code, the executing code and initial fixed array for
736 // active break points.
737 Handle<DebugInfo> debug_info =
738 Handle<DebugInfo>::cast(Factory::NewStruct(DEBUG_INFO_TYPE));
739 debug_info->set_shared(*shared);
740 debug_info->set_original_code(*original_code);
741 debug_info->set_code(*code);
742 debug_info->set_break_points(*break_points);
743
744 // Link debug info to function.
745 shared->set_debug_info(*debug_info);
746
747 return debug_info;
748}
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000749#endif
v8.team.kasperl727e9952008-09-02 14:56:44 +0000750
751
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000752Handle<JSObject> Factory::NewArgumentsObject(Handle<Object> callee,
753 int length) {
754 CALL_HEAP_FUNCTION(Heap::AllocateArgumentsObject(*callee, length), JSObject);
755}
756
757
758Handle<JSFunction> Factory::CreateApiFunction(
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000759 Handle<FunctionTemplateInfo> obj, ApiInstanceType instance_type) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000760 Handle<Code> code = Handle<Code>(Builtins::builtin(Builtins::HandleApiCall));
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000761 Handle<Code> construct_stub =
762 Handle<Code>(Builtins::builtin(Builtins::JSConstructStubApi));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000763
kasper.lund212ac232008-07-16 07:07:30 +0000764 int internal_field_count = 0;
765 if (!obj->instance_template()->IsUndefined()) {
766 Handle<ObjectTemplateInfo> instance_template =
767 Handle<ObjectTemplateInfo>(
768 ObjectTemplateInfo::cast(obj->instance_template()));
769 internal_field_count =
770 Smi::cast(instance_template->internal_field_count())->value();
771 }
772
773 int instance_size = kPointerSize * internal_field_count;
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000774 InstanceType type = INVALID_TYPE;
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000775 switch (instance_type) {
776 case JavaScriptObject:
777 type = JS_OBJECT_TYPE;
778 instance_size += JSObject::kHeaderSize;
779 break;
780 case InnerGlobalObject:
781 type = JS_GLOBAL_OBJECT_TYPE;
782 instance_size += JSGlobalObject::kSize;
783 break;
784 case OuterGlobalObject:
785 type = JS_GLOBAL_PROXY_TYPE;
786 instance_size += JSGlobalProxy::kSize;
787 break;
788 default:
kasperl@chromium.org5a8ca6c2008-10-23 13:57:19 +0000789 break;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000790 }
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000791 ASSERT(type != INVALID_TYPE);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000792
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000793 Handle<JSFunction> result =
ager@chromium.orga74f0da2008-12-03 16:05:52 +0000794 Factory::NewFunction(Factory::empty_symbol(),
795 type,
796 instance_size,
797 code,
798 true);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000799 // Set class name.
800 Handle<Object> class_name = Handle<Object>(obj->class_name());
801 if (class_name->IsString()) {
802 result->shared()->set_instance_class_name(*class_name);
803 result->shared()->set_name(*class_name);
804 }
805
806 Handle<Map> map = Handle<Map>(result->initial_map());
807
808 // Mark as undetectable if needed.
809 if (obj->undetectable()) {
810 map->set_is_undetectable();
811 }
812
813 // Mark as hidden for the __proto__ accessor if needed.
814 if (obj->hidden_prototype()) {
815 map->set_is_hidden_prototype();
816 }
817
818 // Mark as needs_access_check if needed.
819 if (obj->needs_access_check()) {
ager@chromium.org870a0b62008-11-04 11:43:05 +0000820 map->set_is_access_check_needed(true);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000821 }
822
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000823 // Set interceptor information in the map.
824 if (!obj->named_property_handler()->IsUndefined()) {
825 map->set_has_named_interceptor();
826 }
827 if (!obj->indexed_property_handler()->IsUndefined()) {
828 map->set_has_indexed_interceptor();
829 }
830
831 // Set instance call-as-function information in the map.
832 if (!obj->instance_call_handler()->IsUndefined()) {
833 map->set_has_instance_call_handler();
834 }
835
836 result->shared()->set_function_data(*obj);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000837 result->shared()->set_construct_stub(*construct_stub);
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000838 result->shared()->DontAdaptArguments();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000839
840 // Recursively copy parent templates' accessors, 'data' may be modified.
841 Handle<DescriptorArray> array =
842 Handle<DescriptorArray>(map->instance_descriptors());
843 while (true) {
844 Handle<Object> props = Handle<Object>(obj->property_accessors());
845 if (!props->IsUndefined()) {
846 array = Factory::CopyAppendCallbackDescriptors(array, props);
847 }
848 Handle<Object> parent = Handle<Object>(obj->parent_template());
849 if (parent->IsUndefined()) break;
850 obj = Handle<FunctionTemplateInfo>::cast(parent);
851 }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000852 if (!array->IsEmpty()) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000853 map->set_instance_descriptors(*array);
854 }
855
vegorov@chromium.orgf8372902010-03-15 10:26:20 +0000856 ASSERT(result->shared()->IsApiFunction());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000857 return result;
858}
859
860
ager@chromium.org236ad962008-09-25 09:45:57 +0000861Handle<MapCache> Factory::NewMapCache(int at_least_space_for) {
862 CALL_HEAP_FUNCTION(MapCache::Allocate(at_least_space_for), MapCache);
863}
864
865
866static Object* UpdateMapCacheWith(Context* context,
867 FixedArray* keys,
868 Map* map) {
869 Object* result = MapCache::cast(context->map_cache())->Put(keys, map);
870 if (!result->IsFailure()) context->set_map_cache(MapCache::cast(result));
871 return result;
872}
873
874
875Handle<MapCache> Factory::AddToMapCache(Handle<Context> context,
876 Handle<FixedArray> keys,
877 Handle<Map> map) {
878 CALL_HEAP_FUNCTION(UpdateMapCacheWith(*context, *keys, *map), MapCache);
879}
880
881
882Handle<Map> Factory::ObjectLiteralMapFromCache(Handle<Context> context,
883 Handle<FixedArray> keys) {
884 if (context->map_cache()->IsUndefined()) {
885 // Allocate the new map cache for the global context.
886 Handle<MapCache> new_cache = NewMapCache(24);
887 context->set_map_cache(*new_cache);
888 }
ager@chromium.org32912102009-01-16 10:38:43 +0000889 // Check to see whether there is a matching element in the cache.
ager@chromium.org236ad962008-09-25 09:45:57 +0000890 Handle<MapCache> cache =
891 Handle<MapCache>(MapCache::cast(context->map_cache()));
892 Handle<Object> result = Handle<Object>(cache->Lookup(*keys));
893 if (result->IsMap()) return Handle<Map>::cast(result);
894 // Create a new map and add it to the cache.
895 Handle<Map> map =
ager@chromium.org32912102009-01-16 10:38:43 +0000896 CopyMap(Handle<Map>(context->object_function()->initial_map()),
897 keys->length());
ager@chromium.org236ad962008-09-25 09:45:57 +0000898 AddToMapCache(context, keys, map);
899 return Handle<Map>(map);
900}
901
902
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000903void Factory::SetRegExpAtomData(Handle<JSRegExp> regexp,
904 JSRegExp::Type type,
905 Handle<String> source,
906 JSRegExp::Flags flags,
907 Handle<Object> data) {
908 Handle<FixedArray> store = NewFixedArray(JSRegExp::kAtomDataSize);
909
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000910 store->set(JSRegExp::kTagIndex, Smi::FromInt(type));
911 store->set(JSRegExp::kSourceIndex, *source);
912 store->set(JSRegExp::kFlagsIndex, Smi::FromInt(flags.value()));
913 store->set(JSRegExp::kAtomPatternIndex, *data);
914 regexp->set_data(*store);
915}
916
kasperl@chromium.org7be3c992009-03-12 07:19:55 +0000917void Factory::SetRegExpIrregexpData(Handle<JSRegExp> regexp,
918 JSRegExp::Type type,
919 Handle<String> source,
920 JSRegExp::Flags flags,
921 int capture_count) {
922 Handle<FixedArray> store = NewFixedArray(JSRegExp::kIrregexpDataSize);
923
924 store->set(JSRegExp::kTagIndex, Smi::FromInt(type));
925 store->set(JSRegExp::kSourceIndex, *source);
926 store->set(JSRegExp::kFlagsIndex, Smi::FromInt(flags.value()));
927 store->set(JSRegExp::kIrregexpASCIICodeIndex, Heap::the_hole_value());
928 store->set(JSRegExp::kIrregexpUC16CodeIndex, Heap::the_hole_value());
929 store->set(JSRegExp::kIrregexpMaxRegisterCountIndex, Smi::FromInt(0));
930 store->set(JSRegExp::kIrregexpCaptureCountIndex,
931 Smi::FromInt(capture_count));
932 regexp->set_data(*store);
933}
934
935
kasperl@chromium.org9fe21c62008-10-28 08:53:51 +0000936
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000937void Factory::ConfigureInstance(Handle<FunctionTemplateInfo> desc,
938 Handle<JSObject> instance,
939 bool* pending_exception) {
940 // Configure the instance by adding the properties specified by the
941 // instance template.
942 Handle<Object> instance_template = Handle<Object>(desc->instance_template());
943 if (!instance_template->IsUndefined()) {
944 Execution::ConfigureInstance(instance,
945 instance_template,
946 pending_exception);
947 } else {
948 *pending_exception = false;
949 }
950}
951
952
953} } // namespace v8::internal