factory.cc revision 3ce2e2076e8e3e60cf1810eec160ea2d8557e9e7
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 36namespace v8 { 37namespace internal { 38 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 46Handle<FixedArray> Factory::NewFixedArrayWithHoles(int size) { 47 ASSERT(0 <= size); 48 CALL_HEAP_FUNCTION(Heap::AllocateFixedArrayWithHoles(size), FixedArray); 49} 50 51 52Handle<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 59Handle<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 66Handle<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). 74Handle<String> Factory::LookupSymbol(Vector<const char> string) { 75 CALL_HEAP_FUNCTION(Heap::LookupSymbol(string), String); 76} 77 78 79Handle<String> Factory::NewStringFromAscii(Vector<const char> string, 80 PretenureFlag pretenure) { 81 CALL_HEAP_FUNCTION(Heap::AllocateStringFromAscii(string, pretenure), String); 82} 83 84Handle<String> Factory::NewStringFromUtf8(Vector<const char> string, 85 PretenureFlag pretenure) { 86 CALL_HEAP_FUNCTION(Heap::AllocateStringFromUtf8(string, pretenure), String); 87} 88 89 90Handle<String> Factory::NewStringFromTwoByte(Vector<const uc16> string, 91 PretenureFlag pretenure) { 92 CALL_HEAP_FUNCTION(Heap::AllocateStringFromTwoByte(string, pretenure), 93 String); 94} 95 96 97Handle<String> Factory::NewRawTwoByteString(int length, 98 PretenureFlag pretenure) { 99 CALL_HEAP_FUNCTION(Heap::AllocateRawTwoByteString(length, pretenure), String); 100} 101 102 103Handle<String> Factory::NewConsString(Handle<String> first, 104 Handle<String> second) { 105 CALL_HEAP_FUNCTION(Heap::AllocateConsString(*first, *second), String); 106} 107 108 109Handle<String> Factory::NewStringSlice(Handle<String> str, 110 int begin, 111 int end) { 112 CALL_HEAP_FUNCTION(str->Slice(begin, end), String); 113} 114 115 116Handle<String> Factory::NewExternalStringFromAscii( 117 ExternalAsciiString::Resource* resource) { 118 CALL_HEAP_FUNCTION(Heap::AllocateExternalStringFromAscii(resource), String); 119} 120 121 122Handle<String> Factory::NewExternalStringFromTwoByte( 123 ExternalTwoByteString::Resource* resource) { 124 CALL_HEAP_FUNCTION(Heap::AllocateExternalStringFromTwoByte(resource), String); 125} 126 127 128Handle<Context> Factory::NewGlobalContext() { 129 CALL_HEAP_FUNCTION(Heap::AllocateGlobalContext(), Context); 130} 131 132 133Handle<Context> Factory::NewFunctionContext(int length, 134 Handle<JSFunction> closure) { 135 CALL_HEAP_FUNCTION(Heap::AllocateFunctionContext(length, *closure), Context); 136} 137 138 139Handle<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 149Handle<Struct> Factory::NewStruct(InstanceType type) { 150 CALL_HEAP_FUNCTION(Heap::AllocateStruct(type), Struct); 151} 152 153 154Handle<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 162Handle<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 199Handle<Proxy> Factory::NewProxy(Address addr, PretenureFlag pretenure) { 200 CALL_HEAP_FUNCTION(Heap::AllocateProxy(addr, pretenure), Proxy); 201} 202 203 204Handle<Proxy> Factory::NewProxy(const AccessorDescriptor* desc) { 205 return NewProxy((Address) desc, TENURED); 206} 207 208 209Handle<ByteArray> Factory::NewByteArray(int length, PretenureFlag pretenure) { 210 ASSERT(0 <= length); 211 CALL_HEAP_FUNCTION(Heap::AllocateByteArray(length, pretenure), ByteArray); 212} 213 214 215Handle<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 225Handle<ExternalArray> Factory::NewExternalArray(int length, 226 ExternalArrayType array_type, 227 void* external_pointer, 228 PretenureFlag pretenure) { 229 ASSERT(0 <= length); 230 CALL_HEAP_FUNCTION(Heap::AllocateExternalArray(length, 231 array_type, 232 external_pointer, 233 pretenure), ExternalArray); 234} 235 236 237Handle<Map> Factory::NewMap(InstanceType type, int instance_size) { 238 CALL_HEAP_FUNCTION(Heap::AllocateMap(type, instance_size), Map); 239} 240 241 242Handle<JSObject> Factory::NewFunctionPrototype(Handle<JSFunction> function) { 243 CALL_HEAP_FUNCTION(Heap::AllocateFunctionPrototype(*function), JSObject); 244} 245 246 247Handle<Map> Factory::CopyMapDropDescriptors(Handle<Map> src) { 248 CALL_HEAP_FUNCTION(src->CopyDropDescriptors(), Map); 249} 250 251 252Handle<Map> Factory::CopyMap(Handle<Map> src, 253 int extra_inobject_properties) { 254 Handle<Map> copy = CopyMapDropDescriptors(src); 255 // Check that we do not overflow the instance size when adding the 256 // extra inobject properties. 257 int instance_size_delta = extra_inobject_properties * kPointerSize; 258 int max_instance_size_delta = 259 JSObject::kMaxInstanceSize - copy->instance_size(); 260 if (instance_size_delta > max_instance_size_delta) { 261 // If the instance size overflows, we allocate as many properties 262 // as we can as inobject properties. 263 instance_size_delta = max_instance_size_delta; 264 extra_inobject_properties = max_instance_size_delta >> kPointerSizeLog2; 265 } 266 // Adjust the map with the extra inobject properties. 267 int inobject_properties = 268 copy->inobject_properties() + extra_inobject_properties; 269 copy->set_inobject_properties(inobject_properties); 270 copy->set_unused_property_fields(inobject_properties); 271 copy->set_instance_size(copy->instance_size() + instance_size_delta); 272 return copy; 273} 274 275Handle<Map> Factory::CopyMapDropTransitions(Handle<Map> src) { 276 CALL_HEAP_FUNCTION(src->CopyDropTransitions(), Map); 277} 278 279 280Handle<FixedArray> Factory::CopyFixedArray(Handle<FixedArray> array) { 281 CALL_HEAP_FUNCTION(array->Copy(), FixedArray); 282} 283 284 285Handle<JSFunction> Factory::BaseNewFunctionFromBoilerplate( 286 Handle<JSFunction> boilerplate, 287 Handle<Map> function_map) { 288 ASSERT(boilerplate->IsBoilerplate()); 289 ASSERT(!boilerplate->has_initial_map()); 290 ASSERT(!boilerplate->has_prototype()); 291 ASSERT(boilerplate->properties() == Heap::empty_fixed_array()); 292 ASSERT(boilerplate->elements() == Heap::empty_fixed_array()); 293 CALL_HEAP_FUNCTION(Heap::AllocateFunction(*function_map, 294 boilerplate->shared(), 295 Heap::the_hole_value()), 296 JSFunction); 297} 298 299 300Handle<JSFunction> Factory::NewFunctionFromBoilerplate( 301 Handle<JSFunction> boilerplate, 302 Handle<Context> context) { 303 Handle<JSFunction> result = 304 BaseNewFunctionFromBoilerplate(boilerplate, Top::function_map()); 305 result->set_context(*context); 306 int number_of_literals = boilerplate->NumberOfLiterals(); 307 Handle<FixedArray> literals = 308 Factory::NewFixedArray(number_of_literals, TENURED); 309 if (number_of_literals > 0) { 310 // 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. 313 literals->set(JSFunction::kLiteralGlobalContextIndex, 314 context->global_context()); 315 } 316 result->set_literals(*literals); 317 ASSERT(!result->IsBoilerplate()); 318 return result; 319} 320 321 322Handle<Object> Factory::NewNumber(double value, 323 PretenureFlag pretenure) { 324 CALL_HEAP_FUNCTION(Heap::NumberFromDouble(value, pretenure), Object); 325} 326 327 328Handle<Object> Factory::NewNumberFromInt(int value) { 329 CALL_HEAP_FUNCTION(Heap::NumberFromInt32(value), Object); 330} 331 332 333Handle<Object> Factory::NewNumberFromUint(uint32_t value) { 334 CALL_HEAP_FUNCTION(Heap::NumberFromUint32(value), Object); 335} 336 337 338Handle<JSObject> Factory::NewNeanderObject() { 339 CALL_HEAP_FUNCTION(Heap::AllocateJSObjectFromMap(Heap::neander_map()), 340 JSObject); 341} 342 343 344Handle<Object> Factory::NewTypeError(const char* type, 345 Vector< Handle<Object> > args) { 346 return NewError("MakeTypeError", type, args); 347} 348 349 350Handle<Object> Factory::NewTypeError(Handle<String> message) { 351 return NewError("$TypeError", message); 352} 353 354 355Handle<Object> Factory::NewRangeError(const char* type, 356 Vector< Handle<Object> > args) { 357 return NewError("MakeRangeError", type, args); 358} 359 360 361Handle<Object> Factory::NewRangeError(Handle<String> message) { 362 return NewError("$RangeError", message); 363} 364 365 366Handle<Object> Factory::NewSyntaxError(const char* type, Handle<JSArray> args) { 367 return NewError("MakeSyntaxError", type, args); 368} 369 370 371Handle<Object> Factory::NewSyntaxError(Handle<String> message) { 372 return NewError("$SyntaxError", message); 373} 374 375 376Handle<Object> Factory::NewReferenceError(const char* type, 377 Vector< Handle<Object> > args) { 378 return NewError("MakeReferenceError", type, args); 379} 380 381 382Handle<Object> Factory::NewReferenceError(Handle<String> message) { 383 return NewError("$ReferenceError", message); 384} 385 386 387Handle<Object> Factory::NewError(const char* maker, const char* type, 388 Vector< Handle<Object> > args) { 389 v8::HandleScope scope; // Instantiate a closeable HandleScope for EscapeFrom. 390 Handle<FixedArray> array = Factory::NewFixedArray(args.length()); 391 for (int i = 0; i < args.length(); i++) { 392 array->set(i, *args[i]); 393 } 394 Handle<JSArray> object = Factory::NewJSArrayWithElements(array); 395 Handle<Object> result = NewError(maker, type, object); 396 return result.EscapeFrom(&scope); 397} 398 399 400Handle<Object> Factory::NewEvalError(const char* type, 401 Vector< Handle<Object> > args) { 402 return NewError("MakeEvalError", type, args); 403} 404 405 406Handle<Object> Factory::NewError(const char* type, 407 Vector< Handle<Object> > args) { 408 return NewError("MakeError", type, args); 409} 410 411 412Handle<Object> Factory::NewError(const char* maker, 413 const char* type, 414 Handle<JSArray> args) { 415 Handle<String> make_str = Factory::LookupAsciiSymbol(maker); 416 Handle<Object> fun_obj(Top::builtins()->GetProperty(*make_str)); 417 // If the builtins haven't been properly configured yet this error 418 // constructor may not have been defined. Bail out. 419 if (!fun_obj->IsJSFunction()) 420 return Factory::undefined_value(); 421 Handle<JSFunction> fun = Handle<JSFunction>::cast(fun_obj); 422 Handle<Object> type_obj = Factory::LookupAsciiSymbol(type); 423 Object** argv[2] = { type_obj.location(), 424 Handle<Object>::cast(args).location() }; 425 426 // Invoke the JavaScript factory method. If an exception is thrown while 427 // running the factory method, use the exception as the result. 428 bool caught_exception; 429 Handle<Object> result = Execution::TryCall(fun, 430 Top::builtins(), 431 2, 432 argv, 433 &caught_exception); 434 return result; 435} 436 437 438Handle<Object> Factory::NewError(Handle<String> message) { 439 return NewError("$Error", message); 440} 441 442 443Handle<Object> Factory::NewError(const char* constructor, 444 Handle<String> message) { 445 Handle<String> constr = Factory::LookupAsciiSymbol(constructor); 446 Handle<JSFunction> fun = 447 Handle<JSFunction>( 448 JSFunction::cast( 449 Top::builtins()->GetProperty(*constr))); 450 Object** argv[1] = { Handle<Object>::cast(message).location() }; 451 452 // Invoke the JavaScript factory method. If an exception is thrown while 453 // running the factory method, use the exception as the result. 454 bool caught_exception; 455 Handle<Object> result = Execution::TryCall(fun, 456 Top::builtins(), 457 1, 458 argv, 459 &caught_exception); 460 return result; 461} 462 463 464Handle<JSFunction> Factory::NewFunction(Handle<String> name, 465 InstanceType type, 466 int instance_size, 467 Handle<Code> code, 468 bool force_initial_map) { 469 // Allocate the function 470 Handle<JSFunction> function = NewFunction(name, the_hole_value()); 471 function->set_code(*code); 472 473 if (force_initial_map || 474 type != JS_OBJECT_TYPE || 475 instance_size != JSObject::kHeaderSize) { 476 Handle<Map> initial_map = NewMap(type, instance_size); 477 Handle<JSObject> prototype = NewFunctionPrototype(function); 478 initial_map->set_prototype(*prototype); 479 function->set_initial_map(*initial_map); 480 initial_map->set_constructor(*function); 481 } else { 482 ASSERT(!function->has_initial_map()); 483 ASSERT(!function->has_prototype()); 484 } 485 486 return function; 487} 488 489 490Handle<JSFunction> Factory::NewFunctionBoilerplate(Handle<String> name, 491 int number_of_literals, 492 Handle<Code> code) { 493 Handle<JSFunction> function = NewFunctionBoilerplate(name); 494 function->set_code(*code); 495 int literals_array_size = number_of_literals; 496 // If the function contains object, regexp or array literals, 497 // allocate extra space for a literals array prefix containing the 498 // object, regexp and array constructor functions. 499 if (number_of_literals > 0) { 500 literals_array_size += JSFunction::kLiteralsPrefixSize; 501 } 502 Handle<FixedArray> literals = 503 Factory::NewFixedArray(literals_array_size, TENURED); 504 function->set_literals(*literals); 505 ASSERT(!function->has_initial_map()); 506 ASSERT(!function->has_prototype()); 507 return function; 508} 509 510 511Handle<JSFunction> Factory::NewFunctionBoilerplate(Handle<String> name) { 512 Handle<SharedFunctionInfo> shared = NewSharedFunctionInfo(name); 513 CALL_HEAP_FUNCTION(Heap::AllocateFunction(Heap::boilerplate_function_map(), 514 *shared, 515 Heap::the_hole_value()), 516 JSFunction); 517} 518 519 520Handle<JSFunction> Factory::NewFunctionWithPrototype(Handle<String> name, 521 InstanceType type, 522 int instance_size, 523 Handle<JSObject> prototype, 524 Handle<Code> code, 525 bool force_initial_map) { 526 // Allocate the function 527 Handle<JSFunction> function = NewFunction(name, prototype); 528 529 function->set_code(*code); 530 531 if (force_initial_map || 532 type != JS_OBJECT_TYPE || 533 instance_size != JSObject::kHeaderSize) { 534 Handle<Map> initial_map = NewMap(type, instance_size); 535 function->set_initial_map(*initial_map); 536 initial_map->set_constructor(*function); 537 } 538 539 // Set function.prototype and give the prototype a constructor 540 // property that refers to the function. 541 SetPrototypeProperty(function, prototype); 542 SetProperty(prototype, Factory::constructor_symbol(), function, DONT_ENUM); 543 return function; 544} 545 546 547Handle<Code> Factory::NewCode(const CodeDesc& desc, 548 ZoneScopeInfo* sinfo, 549 Code::Flags flags, 550 Handle<Object> self_ref) { 551 CALL_HEAP_FUNCTION(Heap::CreateCode(desc, sinfo, flags, self_ref), Code); 552} 553 554 555Handle<Code> Factory::CopyCode(Handle<Code> code) { 556 CALL_HEAP_FUNCTION(Heap::CopyCode(*code), Code); 557} 558 559 560static inline Object* DoCopyInsert(DescriptorArray* array, 561 String* key, 562 Object* value, 563 PropertyAttributes attributes) { 564 CallbacksDescriptor desc(key, value, attributes); 565 Object* obj = array->CopyInsert(&desc, REMOVE_TRANSITIONS); 566 return obj; 567} 568 569 570// Allocate the new array. 571Handle<DescriptorArray> Factory::CopyAppendProxyDescriptor( 572 Handle<DescriptorArray> array, 573 Handle<String> key, 574 Handle<Object> value, 575 PropertyAttributes attributes) { 576 CALL_HEAP_FUNCTION(DoCopyInsert(*array, *key, *value, attributes), 577 DescriptorArray); 578} 579 580 581Handle<String> Factory::SymbolFromString(Handle<String> value) { 582 CALL_HEAP_FUNCTION(Heap::LookupSymbol(*value), String); 583} 584 585 586Handle<DescriptorArray> Factory::CopyAppendCallbackDescriptors( 587 Handle<DescriptorArray> array, 588 Handle<Object> descriptors) { 589 v8::NeanderArray callbacks(descriptors); 590 int nof_callbacks = callbacks.length(); 591 Handle<DescriptorArray> result = 592 NewDescriptorArray(array->number_of_descriptors() + nof_callbacks); 593 594 // Number of descriptors added to the result so far. 595 int descriptor_count = 0; 596 597 // Copy the descriptors from the array. 598 for (int i = 0; i < array->number_of_descriptors(); i++) { 599 if (array->GetType(i) != NULL_DESCRIPTOR) { 600 result->CopyFrom(descriptor_count++, *array, i); 601 } 602 } 603 604 // Number of duplicates detected. 605 int duplicates = 0; 606 607 // Fill in new callback descriptors. Process the callbacks from 608 // back to front so that the last callback with a given name takes 609 // precedence over previously added callbacks with that name. 610 for (int i = nof_callbacks - 1; i >= 0; i--) { 611 Handle<AccessorInfo> entry = 612 Handle<AccessorInfo>(AccessorInfo::cast(callbacks.get(i))); 613 // Ensure the key is a symbol before writing into the instance descriptor. 614 Handle<String> key = 615 SymbolFromString(Handle<String>(String::cast(entry->name()))); 616 // Check if a descriptor with this name already exists before writing. 617 if (result->LinearSearch(*key, descriptor_count) == 618 DescriptorArray::kNotFound) { 619 CallbacksDescriptor desc(*key, *entry, entry->property_attributes()); 620 result->Set(descriptor_count, &desc); 621 descriptor_count++; 622 } else { 623 duplicates++; 624 } 625 } 626 627 // If duplicates were detected, allocate a result of the right size 628 // and transfer the elements. 629 if (duplicates > 0) { 630 int number_of_descriptors = result->number_of_descriptors() - duplicates; 631 Handle<DescriptorArray> new_result = 632 NewDescriptorArray(number_of_descriptors); 633 for (int i = 0; i < number_of_descriptors; i++) { 634 new_result->CopyFrom(i, *result, i); 635 } 636 result = new_result; 637 } 638 639 // Sort the result before returning. 640 result->Sort(); 641 return result; 642} 643 644 645Handle<JSObject> Factory::NewJSObject(Handle<JSFunction> constructor, 646 PretenureFlag pretenure) { 647 CALL_HEAP_FUNCTION(Heap::AllocateJSObject(*constructor, pretenure), JSObject); 648} 649 650 651Handle<GlobalObject> Factory::NewGlobalObject( 652 Handle<JSFunction> constructor) { 653 CALL_HEAP_FUNCTION(Heap::AllocateGlobalObject(*constructor), 654 GlobalObject); 655} 656 657 658 659Handle<JSObject> Factory::NewJSObjectFromMap(Handle<Map> map) { 660 CALL_HEAP_FUNCTION(Heap::AllocateJSObjectFromMap(*map, NOT_TENURED), 661 JSObject); 662} 663 664 665Handle<JSArray> Factory::NewJSArray(int length, 666 PretenureFlag pretenure) { 667 Handle<JSObject> obj = NewJSObject(Top::array_function(), pretenure); 668 CALL_HEAP_FUNCTION(Handle<JSArray>::cast(obj)->Initialize(length), JSArray); 669} 670 671 672Handle<JSArray> Factory::NewJSArrayWithElements(Handle<FixedArray> elements, 673 PretenureFlag pretenure) { 674 Handle<JSArray> result = 675 Handle<JSArray>::cast(NewJSObject(Top::array_function(), pretenure)); 676 result->SetContent(*elements); 677 return result; 678} 679 680 681Handle<SharedFunctionInfo> Factory::NewSharedFunctionInfo(Handle<String> name) { 682 CALL_HEAP_FUNCTION(Heap::AllocateSharedFunctionInfo(*name), 683 SharedFunctionInfo); 684} 685 686 687Handle<String> Factory::NumberToString(Handle<Object> number) { 688 CALL_HEAP_FUNCTION(Heap::NumberToString(*number), String); 689} 690 691 692Handle<NumberDictionary> Factory::DictionaryAtNumberPut( 693 Handle<NumberDictionary> dictionary, 694 uint32_t key, 695 Handle<Object> value) { 696 CALL_HEAP_FUNCTION(dictionary->AtNumberPut(key, *value), NumberDictionary); 697} 698 699 700Handle<JSFunction> Factory::NewFunctionHelper(Handle<String> name, 701 Handle<Object> prototype) { 702 Handle<SharedFunctionInfo> function_share = NewSharedFunctionInfo(name); 703 CALL_HEAP_FUNCTION(Heap::AllocateFunction(*Top::function_map(), 704 *function_share, 705 *prototype), 706 JSFunction); 707} 708 709 710Handle<JSFunction> Factory::NewFunction(Handle<String> name, 711 Handle<Object> prototype) { 712 Handle<JSFunction> fun = NewFunctionHelper(name, prototype); 713 fun->set_context(Top::context()->global_context()); 714 return fun; 715} 716 717 718Handle<Object> Factory::ToObject(Handle<Object> object, 719 Handle<Context> global_context) { 720 CALL_HEAP_FUNCTION(object->ToObject(*global_context), Object); 721} 722 723 724#ifdef ENABLE_DEBUGGER_SUPPORT 725Handle<DebugInfo> Factory::NewDebugInfo(Handle<SharedFunctionInfo> shared) { 726 // Get the original code of the function. 727 Handle<Code> code(shared->code()); 728 729 // Create a copy of the code before allocating the debug info object to avoid 730 // allocation while setting up the debug info object. 731 Handle<Code> original_code(*Factory::CopyCode(code)); 732 733 // Allocate initial fixed array for active break points before allocating the 734 // debug info object to avoid allocation while setting up the debug info 735 // object. 736 Handle<FixedArray> break_points( 737 Factory::NewFixedArray(Debug::kEstimatedNofBreakPointsInFunction)); 738 739 // Create and set up the debug info object. Debug info contains function, a 740 // copy of the original code, the executing code and initial fixed array for 741 // active break points. 742 Handle<DebugInfo> debug_info = 743 Handle<DebugInfo>::cast(Factory::NewStruct(DEBUG_INFO_TYPE)); 744 debug_info->set_shared(*shared); 745 debug_info->set_original_code(*original_code); 746 debug_info->set_code(*code); 747 debug_info->set_break_points(*break_points); 748 749 // Link debug info to function. 750 shared->set_debug_info(*debug_info); 751 752 return debug_info; 753} 754#endif 755 756 757Handle<JSObject> Factory::NewArgumentsObject(Handle<Object> callee, 758 int length) { 759 CALL_HEAP_FUNCTION(Heap::AllocateArgumentsObject(*callee, length), JSObject); 760} 761 762 763Handle<JSFunction> Factory::CreateApiFunction( 764 Handle<FunctionTemplateInfo> obj, ApiInstanceType instance_type) { 765 Handle<Code> code = Handle<Code>(Builtins::builtin(Builtins::HandleApiCall)); 766 767 int internal_field_count = 0; 768 if (!obj->instance_template()->IsUndefined()) { 769 Handle<ObjectTemplateInfo> instance_template = 770 Handle<ObjectTemplateInfo>( 771 ObjectTemplateInfo::cast(obj->instance_template())); 772 internal_field_count = 773 Smi::cast(instance_template->internal_field_count())->value(); 774 } 775 776 int instance_size = kPointerSize * internal_field_count; 777 InstanceType type = INVALID_TYPE; 778 switch (instance_type) { 779 case JavaScriptObject: 780 type = JS_OBJECT_TYPE; 781 instance_size += JSObject::kHeaderSize; 782 break; 783 case InnerGlobalObject: 784 type = JS_GLOBAL_OBJECT_TYPE; 785 instance_size += JSGlobalObject::kSize; 786 break; 787 case OuterGlobalObject: 788 type = JS_GLOBAL_PROXY_TYPE; 789 instance_size += JSGlobalProxy::kSize; 790 break; 791 default: 792 break; 793 } 794 ASSERT(type != INVALID_TYPE); 795 796 Handle<JSFunction> result = 797 Factory::NewFunction(Factory::empty_symbol(), 798 type, 799 instance_size, 800 code, 801 true); 802 // Set class name. 803 Handle<Object> class_name = Handle<Object>(obj->class_name()); 804 if (class_name->IsString()) { 805 result->shared()->set_instance_class_name(*class_name); 806 result->shared()->set_name(*class_name); 807 } 808 809 Handle<Map> map = Handle<Map>(result->initial_map()); 810 811 // Mark as undetectable if needed. 812 if (obj->undetectable()) { 813 map->set_is_undetectable(); 814 } 815 816 // Mark as hidden for the __proto__ accessor if needed. 817 if (obj->hidden_prototype()) { 818 map->set_is_hidden_prototype(); 819 } 820 821 // Mark as needs_access_check if needed. 822 if (obj->needs_access_check()) { 823 map->set_is_access_check_needed(true); 824 } 825 826 // Set interceptor information in the map. 827 if (!obj->named_property_handler()->IsUndefined()) { 828 map->set_has_named_interceptor(); 829 } 830 if (!obj->indexed_property_handler()->IsUndefined()) { 831 map->set_has_indexed_interceptor(); 832 } 833 834 // Set instance call-as-function information in the map. 835 if (!obj->instance_call_handler()->IsUndefined()) { 836 map->set_has_instance_call_handler(); 837 } 838 839 result->shared()->set_function_data(*obj); 840 result->shared()->DontAdaptArguments(); 841 842 // Recursively copy parent templates' accessors, 'data' may be modified. 843 Handle<DescriptorArray> array = 844 Handle<DescriptorArray>(map->instance_descriptors()); 845 while (true) { 846 Handle<Object> props = Handle<Object>(obj->property_accessors()); 847 if (!props->IsUndefined()) { 848 array = Factory::CopyAppendCallbackDescriptors(array, props); 849 } 850 Handle<Object> parent = Handle<Object>(obj->parent_template()); 851 if (parent->IsUndefined()) break; 852 obj = Handle<FunctionTemplateInfo>::cast(parent); 853 } 854 if (!array->IsEmpty()) { 855 map->set_instance_descriptors(*array); 856 } 857 858 return result; 859} 860 861 862Handle<MapCache> Factory::NewMapCache(int at_least_space_for) { 863 CALL_HEAP_FUNCTION(MapCache::Allocate(at_least_space_for), MapCache); 864} 865 866 867static Object* UpdateMapCacheWith(Context* context, 868 FixedArray* keys, 869 Map* map) { 870 Object* result = MapCache::cast(context->map_cache())->Put(keys, map); 871 if (!result->IsFailure()) context->set_map_cache(MapCache::cast(result)); 872 return result; 873} 874 875 876Handle<MapCache> Factory::AddToMapCache(Handle<Context> context, 877 Handle<FixedArray> keys, 878 Handle<Map> map) { 879 CALL_HEAP_FUNCTION(UpdateMapCacheWith(*context, *keys, *map), MapCache); 880} 881 882 883Handle<Map> Factory::ObjectLiteralMapFromCache(Handle<Context> context, 884 Handle<FixedArray> keys) { 885 if (context->map_cache()->IsUndefined()) { 886 // Allocate the new map cache for the global context. 887 Handle<MapCache> new_cache = NewMapCache(24); 888 context->set_map_cache(*new_cache); 889 } 890 // Check to see whether there is a matching element in the cache. 891 Handle<MapCache> cache = 892 Handle<MapCache>(MapCache::cast(context->map_cache())); 893 Handle<Object> result = Handle<Object>(cache->Lookup(*keys)); 894 if (result->IsMap()) return Handle<Map>::cast(result); 895 // Create a new map and add it to the cache. 896 Handle<Map> map = 897 CopyMap(Handle<Map>(context->object_function()->initial_map()), 898 keys->length()); 899 AddToMapCache(context, keys, map); 900 return Handle<Map>(map); 901} 902 903 904void Factory::SetRegExpAtomData(Handle<JSRegExp> regexp, 905 JSRegExp::Type type, 906 Handle<String> source, 907 JSRegExp::Flags flags, 908 Handle<Object> data) { 909 Handle<FixedArray> store = NewFixedArray(JSRegExp::kAtomDataSize); 910 911 store->set(JSRegExp::kTagIndex, Smi::FromInt(type)); 912 store->set(JSRegExp::kSourceIndex, *source); 913 store->set(JSRegExp::kFlagsIndex, Smi::FromInt(flags.value())); 914 store->set(JSRegExp::kAtomPatternIndex, *data); 915 regexp->set_data(*store); 916} 917 918void Factory::SetRegExpIrregexpData(Handle<JSRegExp> regexp, 919 JSRegExp::Type type, 920 Handle<String> source, 921 JSRegExp::Flags flags, 922 int capture_count) { 923 Handle<FixedArray> store = NewFixedArray(JSRegExp::kIrregexpDataSize); 924 925 store->set(JSRegExp::kTagIndex, Smi::FromInt(type)); 926 store->set(JSRegExp::kSourceIndex, *source); 927 store->set(JSRegExp::kFlagsIndex, Smi::FromInt(flags.value())); 928 store->set(JSRegExp::kIrregexpASCIICodeIndex, Heap::the_hole_value()); 929 store->set(JSRegExp::kIrregexpUC16CodeIndex, Heap::the_hole_value()); 930 store->set(JSRegExp::kIrregexpMaxRegisterCountIndex, Smi::FromInt(0)); 931 store->set(JSRegExp::kIrregexpCaptureCountIndex, 932 Smi::FromInt(capture_count)); 933 regexp->set_data(*store); 934} 935 936 937 938void Factory::ConfigureInstance(Handle<FunctionTemplateInfo> desc, 939 Handle<JSObject> instance, 940 bool* pending_exception) { 941 // Configure the instance by adding the properties specified by the 942 // instance template. 943 Handle<Object> instance_template = Handle<Object>(desc->instance_template()); 944 if (!instance_template->IsUndefined()) { 945 Execution::ConfigureInstance(instance, 946 instance_template, 947 pending_exception); 948 } else { 949 *pending_exception = false; 950 } 951} 952 953 954} } // namespace v8::internal 955