1 // Copyright 2014 the V8 project authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "src/bootstrapper.h" 6 7 #include "src/accessors.h" 8 #include "src/isolate-inl.h" 9 #include "src/natives.h" 10 #include "src/snapshot.h" 11 #include "src/trig-table.h" 12 #include "src/extensions/externalize-string-extension.h" 13 #include "src/extensions/free-buffer-extension.h" 14 #include "src/extensions/gc-extension.h" 15 #include "src/extensions/statistics-extension.h" 16 #include "src/extensions/trigger-failure-extension.h" 17 #include "src/code-stubs.h" 18 19 namespace v8 { 20 namespace internal { 21 22 NativesExternalStringResource::NativesExternalStringResource( 23 Bootstrapper* bootstrapper, 24 const char* source, 25 size_t length) 26 : data_(source), length_(length) { 27 if (bootstrapper->delete_these_non_arrays_on_tear_down_ == NULL) { 28 bootstrapper->delete_these_non_arrays_on_tear_down_ = new List<char*>(2); 29 } 30 // The resources are small objects and we only make a fixed number of 31 // them, but let's clean them up on exit for neatness. 32 bootstrapper->delete_these_non_arrays_on_tear_down_-> 33 Add(reinterpret_cast<char*>(this)); 34 } 35 36 37 Bootstrapper::Bootstrapper(Isolate* isolate) 38 : isolate_(isolate), 39 nesting_(0), 40 extensions_cache_(Script::TYPE_EXTENSION), 41 delete_these_non_arrays_on_tear_down_(NULL), 42 delete_these_arrays_on_tear_down_(NULL) { 43 } 44 45 46 Handle<String> Bootstrapper::NativesSourceLookup(int index) { 47 ASSERT(0 <= index && index < Natives::GetBuiltinsCount()); 48 Heap* heap = isolate_->heap(); 49 if (heap->natives_source_cache()->get(index)->IsUndefined()) { 50 // We can use external strings for the natives. 51 Vector<const char> source = Natives::GetRawScriptSource(index); 52 NativesExternalStringResource* resource = 53 new NativesExternalStringResource(this, 54 source.start(), 55 source.length()); 56 // We do not expect this to throw an exception. Change this if it does. 57 Handle<String> source_code = 58 isolate_->factory()->NewExternalStringFromAscii( 59 resource).ToHandleChecked(); 60 heap->natives_source_cache()->set(index, *source_code); 61 } 62 Handle<Object> cached_source(heap->natives_source_cache()->get(index), 63 isolate_); 64 return Handle<String>::cast(cached_source); 65 } 66 67 68 void Bootstrapper::Initialize(bool create_heap_objects) { 69 extensions_cache_.Initialize(isolate_, create_heap_objects); 70 } 71 72 73 static const char* GCFunctionName() { 74 bool flag_given = FLAG_expose_gc_as != NULL && strlen(FLAG_expose_gc_as) != 0; 75 return flag_given ? FLAG_expose_gc_as : "gc"; 76 } 77 78 79 v8::Extension* Bootstrapper::free_buffer_extension_ = NULL; 80 v8::Extension* Bootstrapper::gc_extension_ = NULL; 81 v8::Extension* Bootstrapper::externalize_string_extension_ = NULL; 82 v8::Extension* Bootstrapper::statistics_extension_ = NULL; 83 v8::Extension* Bootstrapper::trigger_failure_extension_ = NULL; 84 85 86 void Bootstrapper::InitializeOncePerProcess() { 87 free_buffer_extension_ = new FreeBufferExtension; 88 v8::RegisterExtension(free_buffer_extension_); 89 gc_extension_ = new GCExtension(GCFunctionName()); 90 v8::RegisterExtension(gc_extension_); 91 externalize_string_extension_ = new ExternalizeStringExtension; 92 v8::RegisterExtension(externalize_string_extension_); 93 statistics_extension_ = new StatisticsExtension; 94 v8::RegisterExtension(statistics_extension_); 95 trigger_failure_extension_ = new TriggerFailureExtension; 96 v8::RegisterExtension(trigger_failure_extension_); 97 } 98 99 100 void Bootstrapper::TearDownExtensions() { 101 delete free_buffer_extension_; 102 delete gc_extension_; 103 delete externalize_string_extension_; 104 delete statistics_extension_; 105 delete trigger_failure_extension_; 106 } 107 108 109 char* Bootstrapper::AllocateAutoDeletedArray(int bytes) { 110 char* memory = new char[bytes]; 111 if (memory != NULL) { 112 if (delete_these_arrays_on_tear_down_ == NULL) { 113 delete_these_arrays_on_tear_down_ = new List<char*>(2); 114 } 115 delete_these_arrays_on_tear_down_->Add(memory); 116 } 117 return memory; 118 } 119 120 121 void Bootstrapper::TearDown() { 122 if (delete_these_non_arrays_on_tear_down_ != NULL) { 123 int len = delete_these_non_arrays_on_tear_down_->length(); 124 ASSERT(len < 24); // Don't use this mechanism for unbounded allocations. 125 for (int i = 0; i < len; i++) { 126 delete delete_these_non_arrays_on_tear_down_->at(i); 127 delete_these_non_arrays_on_tear_down_->at(i) = NULL; 128 } 129 delete delete_these_non_arrays_on_tear_down_; 130 delete_these_non_arrays_on_tear_down_ = NULL; 131 } 132 133 if (delete_these_arrays_on_tear_down_ != NULL) { 134 int len = delete_these_arrays_on_tear_down_->length(); 135 ASSERT(len < 1000); // Don't use this mechanism for unbounded allocations. 136 for (int i = 0; i < len; i++) { 137 delete[] delete_these_arrays_on_tear_down_->at(i); 138 delete_these_arrays_on_tear_down_->at(i) = NULL; 139 } 140 delete delete_these_arrays_on_tear_down_; 141 delete_these_arrays_on_tear_down_ = NULL; 142 } 143 144 extensions_cache_.Initialize(isolate_, false); // Yes, symmetrical 145 } 146 147 148 class Genesis BASE_EMBEDDED { 149 public: 150 Genesis(Isolate* isolate, 151 Handle<Object> global_object, 152 v8::Handle<v8::ObjectTemplate> global_template, 153 v8::ExtensionConfiguration* extensions); 154 ~Genesis() { } 155 156 Isolate* isolate() const { return isolate_; } 157 Factory* factory() const { return isolate_->factory(); } 158 Heap* heap() const { return isolate_->heap(); } 159 160 Handle<Context> result() { return result_; } 161 162 private: 163 Handle<Context> native_context() { return native_context_; } 164 165 // Creates some basic objects. Used for creating a context from scratch. 166 void CreateRoots(); 167 // Creates the empty function. Used for creating a context from scratch. 168 Handle<JSFunction> CreateEmptyFunction(Isolate* isolate); 169 // Creates the ThrowTypeError function. ECMA 5th Ed. 13.2.3 170 Handle<JSFunction> GetStrictPoisonFunction(); 171 // Poison for sloppy generator function arguments/callee. 172 Handle<JSFunction> GetGeneratorPoisonFunction(); 173 174 void CreateStrictModeFunctionMaps(Handle<JSFunction> empty); 175 176 // Make the "arguments" and "caller" properties throw a TypeError on access. 177 void PoisonArgumentsAndCaller(Handle<Map> map); 178 179 // Creates the global objects using the global and the template passed in 180 // through the API. We call this regardless of whether we are building a 181 // context from scratch or using a deserialized one from the partial snapshot 182 // but in the latter case we don't use the objects it produces directly, as 183 // we have to used the deserialized ones that are linked together with the 184 // rest of the context snapshot. 185 Handle<JSGlobalProxy> CreateNewGlobals( 186 v8::Handle<v8::ObjectTemplate> global_template, 187 Handle<Object> global_object, 188 Handle<GlobalObject>* global_proxy_out); 189 // Hooks the given global proxy into the context. If the context was created 190 // by deserialization then this will unhook the global proxy that was 191 // deserialized, leaving the GC to pick it up. 192 void HookUpGlobalProxy(Handle<GlobalObject> inner_global, 193 Handle<JSGlobalProxy> global_proxy); 194 // Similarly, we want to use the inner global that has been created by the 195 // templates passed through the API. The inner global from the snapshot is 196 // detached from the other objects in the snapshot. 197 void HookUpInnerGlobal(Handle<GlobalObject> inner_global); 198 // New context initialization. Used for creating a context from scratch. 199 void InitializeGlobal(Handle<GlobalObject> inner_global, 200 Handle<JSFunction> empty_function); 201 void InitializeExperimentalGlobal(); 202 // Installs the contents of the native .js files on the global objects. 203 // Used for creating a context from scratch. 204 void InstallNativeFunctions(); 205 void InstallExperimentalBuiltinFunctionIds(); 206 void InstallExperimentalNativeFunctions(); 207 Handle<JSFunction> InstallInternalArray(Handle<JSBuiltinsObject> builtins, 208 const char* name, 209 ElementsKind elements_kind); 210 bool InstallNatives(); 211 212 void InstallTypedArray( 213 const char* name, 214 ElementsKind elements_kind, 215 Handle<JSFunction>* fun, 216 Handle<Map>* external_map); 217 bool InstallExperimentalNatives(); 218 void InstallBuiltinFunctionIds(); 219 void InstallJSFunctionResultCaches(); 220 void InitializeNormalizedMapCaches(); 221 222 enum ExtensionTraversalState { 223 UNVISITED, VISITED, INSTALLED 224 }; 225 226 class ExtensionStates { 227 public: 228 ExtensionStates(); 229 ExtensionTraversalState get_state(RegisteredExtension* extension); 230 void set_state(RegisteredExtension* extension, 231 ExtensionTraversalState state); 232 private: 233 HashMap map_; 234 DISALLOW_COPY_AND_ASSIGN(ExtensionStates); 235 }; 236 237 // Used both for deserialized and from-scratch contexts to add the extensions 238 // provided. 239 static bool InstallExtensions(Handle<Context> native_context, 240 v8::ExtensionConfiguration* extensions); 241 static bool InstallAutoExtensions(Isolate* isolate, 242 ExtensionStates* extension_states); 243 static bool InstallRequestedExtensions(Isolate* isolate, 244 v8::ExtensionConfiguration* extensions, 245 ExtensionStates* extension_states); 246 static bool InstallExtension(Isolate* isolate, 247 const char* name, 248 ExtensionStates* extension_states); 249 static bool InstallExtension(Isolate* isolate, 250 v8::RegisteredExtension* current, 251 ExtensionStates* extension_states); 252 static bool InstallSpecialObjects(Handle<Context> native_context); 253 bool InstallJSBuiltins(Handle<JSBuiltinsObject> builtins); 254 bool ConfigureApiObject(Handle<JSObject> object, 255 Handle<ObjectTemplateInfo> object_template); 256 bool ConfigureGlobalObjects(v8::Handle<v8::ObjectTemplate> global_template); 257 258 // Migrates all properties from the 'from' object to the 'to' 259 // object and overrides the prototype in 'to' with the one from 260 // 'from'. 261 void TransferObject(Handle<JSObject> from, Handle<JSObject> to); 262 void TransferNamedProperties(Handle<JSObject> from, Handle<JSObject> to); 263 void TransferIndexedProperties(Handle<JSObject> from, Handle<JSObject> to); 264 265 enum FunctionMode { 266 // With prototype. 267 FUNCTION_WITH_WRITEABLE_PROTOTYPE, 268 FUNCTION_WITH_READONLY_PROTOTYPE, 269 // Without prototype. 270 FUNCTION_WITHOUT_PROTOTYPE, 271 BOUND_FUNCTION 272 }; 273 274 static bool IsFunctionModeWithPrototype(FunctionMode function_mode) { 275 return (function_mode == FUNCTION_WITH_WRITEABLE_PROTOTYPE || 276 function_mode == FUNCTION_WITH_READONLY_PROTOTYPE); 277 } 278 279 Handle<Map> CreateFunctionMap(FunctionMode function_mode); 280 281 void SetFunctionInstanceDescriptor(Handle<Map> map, 282 FunctionMode function_mode); 283 void MakeFunctionInstancePrototypeWritable(); 284 285 Handle<Map> CreateStrictFunctionMap( 286 FunctionMode function_mode, 287 Handle<JSFunction> empty_function); 288 289 void SetStrictFunctionInstanceDescriptor(Handle<Map> map, 290 FunctionMode function_mode); 291 292 static bool CompileBuiltin(Isolate* isolate, int index); 293 static bool CompileExperimentalBuiltin(Isolate* isolate, int index); 294 static bool CompileNative(Isolate* isolate, 295 Vector<const char> name, 296 Handle<String> source); 297 static bool CompileScriptCached(Isolate* isolate, 298 Vector<const char> name, 299 Handle<String> source, 300 SourceCodeCache* cache, 301 v8::Extension* extension, 302 Handle<Context> top_context, 303 bool use_runtime_context); 304 305 Isolate* isolate_; 306 Handle<Context> result_; 307 Handle<Context> native_context_; 308 309 // Function maps. Function maps are created initially with a read only 310 // prototype for the processing of JS builtins. Later the function maps are 311 // replaced in order to make prototype writable. These are the final, writable 312 // prototype, maps. 313 Handle<Map> sloppy_function_map_writable_prototype_; 314 Handle<Map> strict_function_map_writable_prototype_; 315 Handle<JSFunction> strict_poison_function; 316 Handle<JSFunction> generator_poison_function; 317 318 BootstrapperActive active_; 319 friend class Bootstrapper; 320 }; 321 322 323 void Bootstrapper::Iterate(ObjectVisitor* v) { 324 extensions_cache_.Iterate(v); 325 v->Synchronize(VisitorSynchronization::kExtensions); 326 } 327 328 329 Handle<Context> Bootstrapper::CreateEnvironment( 330 Handle<Object> global_object, 331 v8::Handle<v8::ObjectTemplate> global_template, 332 v8::ExtensionConfiguration* extensions) { 333 HandleScope scope(isolate_); 334 Genesis genesis(isolate_, global_object, global_template, extensions); 335 Handle<Context> env = genesis.result(); 336 if (env.is_null() || !InstallExtensions(env, extensions)) { 337 return Handle<Context>(); 338 } 339 return scope.CloseAndEscape(env); 340 } 341 342 343 static void SetObjectPrototype(Handle<JSObject> object, Handle<Object> proto) { 344 // object.__proto__ = proto; 345 Handle<Map> old_to_map = Handle<Map>(object->map()); 346 Handle<Map> new_to_map = Map::Copy(old_to_map); 347 new_to_map->set_prototype(*proto); 348 object->set_map(*new_to_map); 349 } 350 351 352 void Bootstrapper::DetachGlobal(Handle<Context> env) { 353 Factory* factory = env->GetIsolate()->factory(); 354 Handle<JSGlobalProxy> global_proxy(JSGlobalProxy::cast(env->global_proxy())); 355 global_proxy->set_native_context(*factory->null_value()); 356 SetObjectPrototype(global_proxy, factory->null_value()); 357 } 358 359 360 static Handle<JSFunction> InstallFunction(Handle<JSObject> target, 361 const char* name, 362 InstanceType type, 363 int instance_size, 364 MaybeHandle<JSObject> maybe_prototype, 365 Builtins::Name call) { 366 Isolate* isolate = target->GetIsolate(); 367 Factory* factory = isolate->factory(); 368 Handle<String> internalized_name = factory->InternalizeUtf8String(name); 369 Handle<Code> call_code = Handle<Code>(isolate->builtins()->builtin(call)); 370 Handle<JSObject> prototype; 371 Handle<JSFunction> function = maybe_prototype.ToHandle(&prototype) 372 ? factory->NewFunction(internalized_name, call_code, prototype, 373 type, instance_size) 374 : factory->NewFunctionWithoutPrototype(internalized_name, call_code); 375 PropertyAttributes attributes; 376 if (target->IsJSBuiltinsObject()) { 377 attributes = 378 static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE | READ_ONLY); 379 } else { 380 attributes = DONT_ENUM; 381 } 382 JSObject::SetOwnPropertyIgnoreAttributes( 383 target, internalized_name, function, attributes).Check(); 384 if (target->IsJSGlobalObject()) { 385 function->shared()->set_instance_class_name(*internalized_name); 386 } 387 function->shared()->set_native(true); 388 return function; 389 } 390 391 392 void Genesis::SetFunctionInstanceDescriptor( 393 Handle<Map> map, FunctionMode function_mode) { 394 int size = IsFunctionModeWithPrototype(function_mode) ? 5 : 4; 395 Map::EnsureDescriptorSlack(map, size); 396 397 PropertyAttributes attribs = static_cast<PropertyAttributes>( 398 DONT_ENUM | DONT_DELETE | READ_ONLY); 399 400 Handle<AccessorInfo> length = 401 Accessors::FunctionLengthInfo(isolate(), attribs); 402 { // Add length. 403 CallbacksDescriptor d(Handle<Name>(Name::cast(length->name())), 404 length, attribs); 405 map->AppendDescriptor(&d); 406 } 407 Handle<AccessorInfo> name = 408 Accessors::FunctionNameInfo(isolate(), attribs); 409 { // Add name. 410 CallbacksDescriptor d(Handle<Name>(Name::cast(name->name())), 411 name, attribs); 412 map->AppendDescriptor(&d); 413 } 414 Handle<AccessorInfo> args = 415 Accessors::FunctionArgumentsInfo(isolate(), attribs); 416 { // Add arguments. 417 CallbacksDescriptor d(Handle<Name>(Name::cast(args->name())), 418 args, attribs); 419 map->AppendDescriptor(&d); 420 } 421 Handle<AccessorInfo> caller = 422 Accessors::FunctionCallerInfo(isolate(), attribs); 423 { // Add caller. 424 CallbacksDescriptor d(Handle<Name>(Name::cast(caller->name())), 425 caller, attribs); 426 map->AppendDescriptor(&d); 427 } 428 if (IsFunctionModeWithPrototype(function_mode)) { 429 if (function_mode == FUNCTION_WITH_WRITEABLE_PROTOTYPE) { 430 attribs = static_cast<PropertyAttributes>(attribs & ~READ_ONLY); 431 } 432 Handle<AccessorInfo> prototype = 433 Accessors::FunctionPrototypeInfo(isolate(), attribs); 434 CallbacksDescriptor d(Handle<Name>(Name::cast(prototype->name())), 435 prototype, attribs); 436 map->AppendDescriptor(&d); 437 } 438 } 439 440 441 Handle<Map> Genesis::CreateFunctionMap(FunctionMode function_mode) { 442 Handle<Map> map = factory()->NewMap(JS_FUNCTION_TYPE, JSFunction::kSize); 443 SetFunctionInstanceDescriptor(map, function_mode); 444 map->set_function_with_prototype(IsFunctionModeWithPrototype(function_mode)); 445 return map; 446 } 447 448 449 Handle<JSFunction> Genesis::CreateEmptyFunction(Isolate* isolate) { 450 // Allocate the map for function instances. Maps are allocated first and their 451 // prototypes patched later, once empty function is created. 452 453 // Functions with this map will not have a 'prototype' property, and 454 // can not be used as constructors. 455 Handle<Map> function_without_prototype_map = 456 CreateFunctionMap(FUNCTION_WITHOUT_PROTOTYPE); 457 native_context()->set_sloppy_function_without_prototype_map( 458 *function_without_prototype_map); 459 460 // Allocate the function map. This map is temporary, used only for processing 461 // of builtins. 462 // Later the map is replaced with writable prototype map, allocated below. 463 Handle<Map> function_map = 464 CreateFunctionMap(FUNCTION_WITH_READONLY_PROTOTYPE); 465 native_context()->set_sloppy_function_map(*function_map); 466 native_context()->set_sloppy_function_with_readonly_prototype_map( 467 *function_map); 468 469 // The final map for functions. Writeable prototype. 470 // This map is installed in MakeFunctionInstancePrototypeWritable. 471 sloppy_function_map_writable_prototype_ = 472 CreateFunctionMap(FUNCTION_WITH_WRITEABLE_PROTOTYPE); 473 474 Factory* factory = isolate->factory(); 475 476 Handle<String> object_name = factory->Object_string(); 477 478 { // --- O b j e c t --- 479 Handle<JSFunction> object_fun = factory->NewFunction(object_name); 480 Handle<Map> object_function_map = 481 factory->NewMap(JS_OBJECT_TYPE, JSObject::kHeaderSize); 482 object_fun->set_initial_map(*object_function_map); 483 object_function_map->set_constructor(*object_fun); 484 object_function_map->set_unused_property_fields( 485 JSObject::kInitialGlobalObjectUnusedPropertiesCount); 486 487 native_context()->set_object_function(*object_fun); 488 489 // Allocate a new prototype for the object function. 490 Handle<JSObject> prototype = factory->NewJSObject( 491 isolate->object_function(), 492 TENURED); 493 494 native_context()->set_initial_object_prototype(*prototype); 495 // For bootstrapping set the array prototype to be the same as the object 496 // prototype, otherwise the missing initial_array_prototype will cause 497 // assertions during startup. 498 native_context()->set_initial_array_prototype(*prototype); 499 Accessors::FunctionSetPrototype(object_fun, prototype); 500 } 501 502 // Allocate the empty function as the prototype for function ECMAScript 503 // 262 15.3.4. 504 Handle<String> empty_string = 505 factory->InternalizeOneByteString(STATIC_ASCII_VECTOR("Empty")); 506 Handle<Code> code(isolate->builtins()->builtin(Builtins::kEmptyFunction)); 507 Handle<JSFunction> empty_function = factory->NewFunctionWithoutPrototype( 508 empty_string, code); 509 510 // --- E m p t y --- 511 Handle<String> source = factory->NewStringFromStaticAscii("() {}"); 512 Handle<Script> script = factory->NewScript(source); 513 script->set_type(Smi::FromInt(Script::TYPE_NATIVE)); 514 empty_function->shared()->set_script(*script); 515 empty_function->shared()->set_start_position(0); 516 empty_function->shared()->set_end_position(source->length()); 517 empty_function->shared()->DontAdaptArguments(); 518 519 // Set prototypes for the function maps. 520 native_context()->sloppy_function_map()->set_prototype(*empty_function); 521 native_context()->sloppy_function_without_prototype_map()-> 522 set_prototype(*empty_function); 523 sloppy_function_map_writable_prototype_->set_prototype(*empty_function); 524 525 // Allocate the function map first and then patch the prototype later 526 Handle<Map> empty_function_map = 527 CreateFunctionMap(FUNCTION_WITHOUT_PROTOTYPE); 528 empty_function_map->set_prototype( 529 native_context()->object_function()->prototype()); 530 empty_function->set_map(*empty_function_map); 531 return empty_function; 532 } 533 534 535 void Genesis::SetStrictFunctionInstanceDescriptor( 536 Handle<Map> map, FunctionMode function_mode) { 537 int size = IsFunctionModeWithPrototype(function_mode) ? 5 : 4; 538 Map::EnsureDescriptorSlack(map, size); 539 540 Handle<AccessorPair> arguments(factory()->NewAccessorPair()); 541 Handle<AccessorPair> caller(factory()->NewAccessorPair()); 542 PropertyAttributes rw_attribs = 543 static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE); 544 PropertyAttributes ro_attribs = 545 static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE | READ_ONLY); 546 547 // Add length. 548 if (function_mode == BOUND_FUNCTION) { 549 Handle<String> length_string = isolate()->factory()->length_string(); 550 FieldDescriptor d(length_string, 0, ro_attribs, Representation::Tagged()); 551 map->AppendDescriptor(&d); 552 } else { 553 ASSERT(function_mode == FUNCTION_WITH_WRITEABLE_PROTOTYPE || 554 function_mode == FUNCTION_WITH_READONLY_PROTOTYPE || 555 function_mode == FUNCTION_WITHOUT_PROTOTYPE); 556 Handle<AccessorInfo> length = 557 Accessors::FunctionLengthInfo(isolate(), ro_attribs); 558 CallbacksDescriptor d(Handle<Name>(Name::cast(length->name())), 559 length, ro_attribs); 560 map->AppendDescriptor(&d); 561 } 562 Handle<AccessorInfo> name = 563 Accessors::FunctionNameInfo(isolate(), ro_attribs); 564 { // Add name. 565 CallbacksDescriptor d(Handle<Name>(Name::cast(name->name())), 566 name, ro_attribs); 567 map->AppendDescriptor(&d); 568 } 569 { // Add arguments. 570 CallbacksDescriptor d(factory()->arguments_string(), arguments, 571 rw_attribs); 572 map->AppendDescriptor(&d); 573 } 574 { // Add caller. 575 CallbacksDescriptor d(factory()->caller_string(), caller, rw_attribs); 576 map->AppendDescriptor(&d); 577 } 578 if (IsFunctionModeWithPrototype(function_mode)) { 579 // Add prototype. 580 PropertyAttributes attribs = 581 function_mode == FUNCTION_WITH_WRITEABLE_PROTOTYPE ? rw_attribs 582 : ro_attribs; 583 Handle<AccessorInfo> prototype = 584 Accessors::FunctionPrototypeInfo(isolate(), attribs); 585 CallbacksDescriptor d(Handle<Name>(Name::cast(prototype->name())), 586 prototype, attribs); 587 map->AppendDescriptor(&d); 588 } 589 } 590 591 592 // ECMAScript 5th Edition, 13.2.3 593 Handle<JSFunction> Genesis::GetStrictPoisonFunction() { 594 if (strict_poison_function.is_null()) { 595 Handle<String> name = factory()->InternalizeOneByteString( 596 STATIC_ASCII_VECTOR("ThrowTypeError")); 597 Handle<Code> code(isolate()->builtins()->builtin( 598 Builtins::kStrictModePoisonPill)); 599 strict_poison_function = factory()->NewFunctionWithoutPrototype(name, code); 600 strict_poison_function->set_map(native_context()->sloppy_function_map()); 601 strict_poison_function->shared()->DontAdaptArguments(); 602 603 JSObject::PreventExtensions(strict_poison_function).Assert(); 604 } 605 return strict_poison_function; 606 } 607 608 609 Handle<JSFunction> Genesis::GetGeneratorPoisonFunction() { 610 if (generator_poison_function.is_null()) { 611 Handle<String> name = factory()->InternalizeOneByteString( 612 STATIC_ASCII_VECTOR("ThrowTypeError")); 613 Handle<Code> code(isolate()->builtins()->builtin( 614 Builtins::kGeneratorPoisonPill)); 615 generator_poison_function = factory()->NewFunctionWithoutPrototype( 616 name, code); 617 generator_poison_function->set_map(native_context()->sloppy_function_map()); 618 generator_poison_function->shared()->DontAdaptArguments(); 619 620 JSObject::PreventExtensions(generator_poison_function).Assert(); 621 } 622 return generator_poison_function; 623 } 624 625 626 Handle<Map> Genesis::CreateStrictFunctionMap( 627 FunctionMode function_mode, 628 Handle<JSFunction> empty_function) { 629 Handle<Map> map = factory()->NewMap(JS_FUNCTION_TYPE, JSFunction::kSize); 630 SetStrictFunctionInstanceDescriptor(map, function_mode); 631 map->set_function_with_prototype(IsFunctionModeWithPrototype(function_mode)); 632 map->set_prototype(*empty_function); 633 return map; 634 } 635 636 637 void Genesis::CreateStrictModeFunctionMaps(Handle<JSFunction> empty) { 638 // Allocate map for the prototype-less strict mode instances. 639 Handle<Map> strict_function_without_prototype_map = 640 CreateStrictFunctionMap(FUNCTION_WITHOUT_PROTOTYPE, empty); 641 native_context()->set_strict_function_without_prototype_map( 642 *strict_function_without_prototype_map); 643 644 // Allocate map for the strict mode functions. This map is temporary, used 645 // only for processing of builtins. 646 // Later the map is replaced with writable prototype map, allocated below. 647 Handle<Map> strict_function_map = 648 CreateStrictFunctionMap(FUNCTION_WITH_READONLY_PROTOTYPE, empty); 649 native_context()->set_strict_function_map(*strict_function_map); 650 651 // The final map for the strict mode functions. Writeable prototype. 652 // This map is installed in MakeFunctionInstancePrototypeWritable. 653 strict_function_map_writable_prototype_ = 654 CreateStrictFunctionMap(FUNCTION_WITH_WRITEABLE_PROTOTYPE, empty); 655 // Special map for bound functions. 656 Handle<Map> bound_function_map = 657 CreateStrictFunctionMap(BOUND_FUNCTION, empty); 658 native_context()->set_bound_function_map(*bound_function_map); 659 660 // Complete the callbacks. 661 PoisonArgumentsAndCaller(strict_function_without_prototype_map); 662 PoisonArgumentsAndCaller(strict_function_map); 663 PoisonArgumentsAndCaller(strict_function_map_writable_prototype_); 664 PoisonArgumentsAndCaller(bound_function_map); 665 } 666 667 668 static void SetAccessors(Handle<Map> map, 669 Handle<String> name, 670 Handle<JSFunction> func) { 671 DescriptorArray* descs = map->instance_descriptors(); 672 int number = descs->SearchWithCache(*name, *map); 673 AccessorPair* accessors = AccessorPair::cast(descs->GetValue(number)); 674 accessors->set_getter(*func); 675 accessors->set_setter(*func); 676 } 677 678 679 static void ReplaceAccessors(Handle<Map> map, 680 Handle<String> name, 681 PropertyAttributes attributes, 682 Handle<AccessorPair> accessor_pair) { 683 DescriptorArray* descriptors = map->instance_descriptors(); 684 int idx = descriptors->SearchWithCache(*name, *map); 685 CallbacksDescriptor descriptor(name, accessor_pair, attributes); 686 descriptors->Replace(idx, &descriptor); 687 } 688 689 690 void Genesis::PoisonArgumentsAndCaller(Handle<Map> map) { 691 SetAccessors(map, factory()->arguments_string(), GetStrictPoisonFunction()); 692 SetAccessors(map, factory()->caller_string(), GetStrictPoisonFunction()); 693 } 694 695 696 static void AddToWeakNativeContextList(Context* context) { 697 ASSERT(context->IsNativeContext()); 698 Heap* heap = context->GetIsolate()->heap(); 699 #ifdef DEBUG 700 { // NOLINT 701 ASSERT(context->get(Context::NEXT_CONTEXT_LINK)->IsUndefined()); 702 // Check that context is not in the list yet. 703 for (Object* current = heap->native_contexts_list(); 704 !current->IsUndefined(); 705 current = Context::cast(current)->get(Context::NEXT_CONTEXT_LINK)) { 706 ASSERT(current != context); 707 } 708 } 709 #endif 710 context->set(Context::NEXT_CONTEXT_LINK, heap->native_contexts_list()); 711 heap->set_native_contexts_list(context); 712 } 713 714 715 void Genesis::CreateRoots() { 716 // Allocate the native context FixedArray first and then patch the 717 // closure and extension object later (we need the empty function 718 // and the global object, but in order to create those, we need the 719 // native context). 720 native_context_ = factory()->NewNativeContext(); 721 AddToWeakNativeContextList(*native_context()); 722 isolate()->set_context(*native_context()); 723 724 // Allocate the message listeners object. 725 { 726 v8::NeanderArray listeners(isolate()); 727 native_context()->set_message_listeners(*listeners.value()); 728 } 729 } 730 731 732 Handle<JSGlobalProxy> Genesis::CreateNewGlobals( 733 v8::Handle<v8::ObjectTemplate> global_template, 734 Handle<Object> global_object, 735 Handle<GlobalObject>* inner_global_out) { 736 // The argument global_template aka data is an ObjectTemplateInfo. 737 // It has a constructor pointer that points at global_constructor which is a 738 // FunctionTemplateInfo. 739 // The global_constructor is used to create or reinitialize the global_proxy. 740 // The global_constructor also has a prototype_template pointer that points at 741 // js_global_template which is an ObjectTemplateInfo. 742 // That in turn has a constructor pointer that points at 743 // js_global_constructor which is a FunctionTemplateInfo. 744 // js_global_constructor is used to make js_global_function 745 // js_global_function is used to make the new inner_global. 746 // 747 // --- G l o b a l --- 748 // Step 1: Create a fresh inner JSGlobalObject. 749 Handle<JSFunction> js_global_function; 750 Handle<ObjectTemplateInfo> js_global_template; 751 if (!global_template.IsEmpty()) { 752 // Get prototype template of the global_template. 753 Handle<ObjectTemplateInfo> data = 754 v8::Utils::OpenHandle(*global_template); 755 Handle<FunctionTemplateInfo> global_constructor = 756 Handle<FunctionTemplateInfo>( 757 FunctionTemplateInfo::cast(data->constructor())); 758 Handle<Object> proto_template(global_constructor->prototype_template(), 759 isolate()); 760 if (!proto_template->IsUndefined()) { 761 js_global_template = 762 Handle<ObjectTemplateInfo>::cast(proto_template); 763 } 764 } 765 766 if (js_global_template.is_null()) { 767 Handle<String> name = Handle<String>(heap()->empty_string()); 768 Handle<Code> code = Handle<Code>(isolate()->builtins()->builtin( 769 Builtins::kIllegal)); 770 js_global_function = factory()->NewFunction( 771 name, code, JS_GLOBAL_OBJECT_TYPE, JSGlobalObject::kSize); 772 // Change the constructor property of the prototype of the 773 // hidden global function to refer to the Object function. 774 Handle<JSObject> prototype = 775 Handle<JSObject>( 776 JSObject::cast(js_global_function->instance_prototype())); 777 JSObject::SetOwnPropertyIgnoreAttributes( 778 prototype, factory()->constructor_string(), 779 isolate()->object_function(), NONE).Check(); 780 } else { 781 Handle<FunctionTemplateInfo> js_global_constructor( 782 FunctionTemplateInfo::cast(js_global_template->constructor())); 783 js_global_function = 784 factory()->CreateApiFunction(js_global_constructor, 785 factory()->the_hole_value(), 786 factory()->InnerGlobalObject); 787 } 788 789 js_global_function->initial_map()->set_is_hidden_prototype(); 790 js_global_function->initial_map()->set_dictionary_map(true); 791 Handle<GlobalObject> inner_global = 792 factory()->NewGlobalObject(js_global_function); 793 if (inner_global_out != NULL) { 794 *inner_global_out = inner_global; 795 } 796 797 // Step 2: create or re-initialize the global proxy object. 798 Handle<JSFunction> global_proxy_function; 799 if (global_template.IsEmpty()) { 800 Handle<String> name = Handle<String>(heap()->empty_string()); 801 Handle<Code> code = Handle<Code>(isolate()->builtins()->builtin( 802 Builtins::kIllegal)); 803 global_proxy_function = factory()->NewFunction( 804 name, code, JS_GLOBAL_PROXY_TYPE, JSGlobalProxy::kSize); 805 } else { 806 Handle<ObjectTemplateInfo> data = 807 v8::Utils::OpenHandle(*global_template); 808 Handle<FunctionTemplateInfo> global_constructor( 809 FunctionTemplateInfo::cast(data->constructor())); 810 global_proxy_function = 811 factory()->CreateApiFunction(global_constructor, 812 factory()->the_hole_value(), 813 factory()->OuterGlobalObject); 814 } 815 816 Handle<String> global_name = factory()->InternalizeOneByteString( 817 STATIC_ASCII_VECTOR("global")); 818 global_proxy_function->shared()->set_instance_class_name(*global_name); 819 global_proxy_function->initial_map()->set_is_access_check_needed(true); 820 821 // Set global_proxy.__proto__ to js_global after ConfigureGlobalObjects 822 // Return the global proxy. 823 824 Handle<JSGlobalProxy> global_proxy; 825 if (global_object.location() != NULL) { 826 ASSERT(global_object->IsJSGlobalProxy()); 827 global_proxy = Handle<JSGlobalProxy>::cast(global_object); 828 factory()->ReinitializeJSGlobalProxy(global_proxy, global_proxy_function); 829 } else { 830 global_proxy = Handle<JSGlobalProxy>::cast( 831 factory()->NewJSObject(global_proxy_function, TENURED)); 832 global_proxy->set_hash(heap()->undefined_value()); 833 } 834 return global_proxy; 835 } 836 837 838 void Genesis::HookUpGlobalProxy(Handle<GlobalObject> inner_global, 839 Handle<JSGlobalProxy> global_proxy) { 840 // Set the native context for the global object. 841 inner_global->set_native_context(*native_context()); 842 inner_global->set_global_context(*native_context()); 843 inner_global->set_global_receiver(*global_proxy); 844 global_proxy->set_native_context(*native_context()); 845 native_context()->set_global_proxy(*global_proxy); 846 } 847 848 849 void Genesis::HookUpInnerGlobal(Handle<GlobalObject> inner_global) { 850 Handle<GlobalObject> inner_global_from_snapshot( 851 GlobalObject::cast(native_context()->extension())); 852 Handle<JSBuiltinsObject> builtins_global(native_context()->builtins()); 853 native_context()->set_extension(*inner_global); 854 native_context()->set_global_object(*inner_global); 855 native_context()->set_security_token(*inner_global); 856 static const PropertyAttributes attributes = 857 static_cast<PropertyAttributes>(READ_ONLY | DONT_DELETE); 858 Runtime::ForceSetObjectProperty(builtins_global, 859 factory()->InternalizeOneByteString( 860 STATIC_ASCII_VECTOR("global")), 861 inner_global, 862 attributes).Assert(); 863 // Set up the reference from the global object to the builtins object. 864 JSGlobalObject::cast(*inner_global)->set_builtins(*builtins_global); 865 TransferNamedProperties(inner_global_from_snapshot, inner_global); 866 TransferIndexedProperties(inner_global_from_snapshot, inner_global); 867 } 868 869 870 // This is only called if we are not using snapshots. The equivalent 871 // work in the snapshot case is done in HookUpInnerGlobal. 872 void Genesis::InitializeGlobal(Handle<GlobalObject> inner_global, 873 Handle<JSFunction> empty_function) { 874 // --- N a t i v e C o n t e x t --- 875 // Use the empty function as closure (no scope info). 876 native_context()->set_closure(*empty_function); 877 native_context()->set_previous(NULL); 878 // Set extension and global object. 879 native_context()->set_extension(*inner_global); 880 native_context()->set_global_object(*inner_global); 881 // Security setup: Set the security token of the global object to 882 // its the inner global. This makes the security check between two 883 // different contexts fail by default even in case of global 884 // object reinitialization. 885 native_context()->set_security_token(*inner_global); 886 887 Isolate* isolate = inner_global->GetIsolate(); 888 Factory* factory = isolate->factory(); 889 Heap* heap = isolate->heap(); 890 891 Handle<String> object_name = factory->Object_string(); 892 JSObject::SetOwnPropertyIgnoreAttributes( 893 inner_global, object_name, 894 isolate->object_function(), DONT_ENUM).Check(); 895 896 Handle<JSObject> global(native_context()->global_object()); 897 898 // Install global Function object 899 InstallFunction(global, "Function", JS_FUNCTION_TYPE, JSFunction::kSize, 900 empty_function, Builtins::kIllegal); 901 902 { // --- A r r a y --- 903 Handle<JSFunction> array_function = 904 InstallFunction(global, "Array", JS_ARRAY_TYPE, JSArray::kSize, 905 isolate->initial_object_prototype(), 906 Builtins::kArrayCode); 907 array_function->shared()->DontAdaptArguments(); 908 array_function->shared()->set_function_data(Smi::FromInt(kArrayCode)); 909 910 // This seems a bit hackish, but we need to make sure Array.length 911 // is 1. 912 array_function->shared()->set_length(1); 913 914 Handle<Map> initial_map(array_function->initial_map()); 915 916 // This assert protects an optimization in 917 // HGraphBuilder::JSArrayBuilder::EmitMapCode() 918 ASSERT(initial_map->elements_kind() == GetInitialFastElementsKind()); 919 Map::EnsureDescriptorSlack(initial_map, 1); 920 921 PropertyAttributes attribs = static_cast<PropertyAttributes>( 922 DONT_ENUM | DONT_DELETE); 923 924 Handle<AccessorInfo> array_length = 925 Accessors::ArrayLengthInfo(isolate, attribs); 926 { // Add length. 927 CallbacksDescriptor d( 928 Handle<Name>(Name::cast(array_length->name())), 929 array_length, attribs); 930 array_function->initial_map()->AppendDescriptor(&d); 931 } 932 933 // array_function is used internally. JS code creating array object should 934 // search for the 'Array' property on the global object and use that one 935 // as the constructor. 'Array' property on a global object can be 936 // overwritten by JS code. 937 native_context()->set_array_function(*array_function); 938 939 // Cache the array maps, needed by ArrayConstructorStub 940 CacheInitialJSArrayMaps(native_context(), initial_map); 941 ArrayConstructorStub array_constructor_stub(isolate); 942 Handle<Code> code = array_constructor_stub.GetCode(); 943 array_function->shared()->set_construct_stub(*code); 944 } 945 946 { // --- N u m b e r --- 947 Handle<JSFunction> number_fun = 948 InstallFunction(global, "Number", JS_VALUE_TYPE, JSValue::kSize, 949 isolate->initial_object_prototype(), 950 Builtins::kIllegal); 951 native_context()->set_number_function(*number_fun); 952 } 953 954 { // --- B o o l e a n --- 955 Handle<JSFunction> boolean_fun = 956 InstallFunction(global, "Boolean", JS_VALUE_TYPE, JSValue::kSize, 957 isolate->initial_object_prototype(), 958 Builtins::kIllegal); 959 native_context()->set_boolean_function(*boolean_fun); 960 } 961 962 { // --- S t r i n g --- 963 Handle<JSFunction> string_fun = 964 InstallFunction(global, "String", JS_VALUE_TYPE, JSValue::kSize, 965 isolate->initial_object_prototype(), 966 Builtins::kIllegal); 967 string_fun->shared()->set_construct_stub( 968 isolate->builtins()->builtin(Builtins::kStringConstructCode)); 969 native_context()->set_string_function(*string_fun); 970 971 Handle<Map> string_map = 972 Handle<Map>(native_context()->string_function()->initial_map()); 973 Map::EnsureDescriptorSlack(string_map, 1); 974 975 PropertyAttributes attribs = static_cast<PropertyAttributes>( 976 DONT_ENUM | DONT_DELETE | READ_ONLY); 977 Handle<AccessorInfo> string_length( 978 Accessors::StringLengthInfo(isolate, attribs)); 979 980 { // Add length. 981 CallbacksDescriptor d(factory->length_string(), string_length, attribs); 982 string_map->AppendDescriptor(&d); 983 } 984 } 985 986 { // --- D a t e --- 987 // Builtin functions for Date.prototype. 988 Handle<JSFunction> date_fun = 989 InstallFunction(global, "Date", JS_DATE_TYPE, JSDate::kSize, 990 isolate->initial_object_prototype(), 991 Builtins::kIllegal); 992 993 native_context()->set_date_function(*date_fun); 994 } 995 996 997 { // -- R e g E x p 998 // Builtin functions for RegExp.prototype. 999 Handle<JSFunction> regexp_fun = 1000 InstallFunction(global, "RegExp", JS_REGEXP_TYPE, JSRegExp::kSize, 1001 isolate->initial_object_prototype(), 1002 Builtins::kIllegal); 1003 native_context()->set_regexp_function(*regexp_fun); 1004 1005 ASSERT(regexp_fun->has_initial_map()); 1006 Handle<Map> initial_map(regexp_fun->initial_map()); 1007 1008 ASSERT_EQ(0, initial_map->inobject_properties()); 1009 1010 PropertyAttributes final = 1011 static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE | READ_ONLY); 1012 Map::EnsureDescriptorSlack(initial_map, 5); 1013 1014 { 1015 // ECMA-262, section 15.10.7.1. 1016 FieldDescriptor field(factory->source_string(), 1017 JSRegExp::kSourceFieldIndex, 1018 final, 1019 Representation::Tagged()); 1020 initial_map->AppendDescriptor(&field); 1021 } 1022 { 1023 // ECMA-262, section 15.10.7.2. 1024 FieldDescriptor field(factory->global_string(), 1025 JSRegExp::kGlobalFieldIndex, 1026 final, 1027 Representation::Tagged()); 1028 initial_map->AppendDescriptor(&field); 1029 } 1030 { 1031 // ECMA-262, section 15.10.7.3. 1032 FieldDescriptor field(factory->ignore_case_string(), 1033 JSRegExp::kIgnoreCaseFieldIndex, 1034 final, 1035 Representation::Tagged()); 1036 initial_map->AppendDescriptor(&field); 1037 } 1038 { 1039 // ECMA-262, section 15.10.7.4. 1040 FieldDescriptor field(factory->multiline_string(), 1041 JSRegExp::kMultilineFieldIndex, 1042 final, 1043 Representation::Tagged()); 1044 initial_map->AppendDescriptor(&field); 1045 } 1046 { 1047 // ECMA-262, section 15.10.7.5. 1048 PropertyAttributes writable = 1049 static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE); 1050 FieldDescriptor field(factory->last_index_string(), 1051 JSRegExp::kLastIndexFieldIndex, 1052 writable, 1053 Representation::Tagged()); 1054 initial_map->AppendDescriptor(&field); 1055 } 1056 1057 initial_map->set_inobject_properties(5); 1058 initial_map->set_pre_allocated_property_fields(5); 1059 initial_map->set_unused_property_fields(0); 1060 initial_map->set_instance_size( 1061 initial_map->instance_size() + 5 * kPointerSize); 1062 initial_map->set_visitor_id(StaticVisitorBase::GetVisitorId(*initial_map)); 1063 1064 // RegExp prototype object is itself a RegExp. 1065 Handle<Map> proto_map = Map::Copy(initial_map); 1066 proto_map->set_prototype(native_context()->initial_object_prototype()); 1067 Handle<JSObject> proto = factory->NewJSObjectFromMap(proto_map); 1068 proto->InObjectPropertyAtPut(JSRegExp::kSourceFieldIndex, 1069 heap->query_colon_string()); 1070 proto->InObjectPropertyAtPut(JSRegExp::kGlobalFieldIndex, 1071 heap->false_value()); 1072 proto->InObjectPropertyAtPut(JSRegExp::kIgnoreCaseFieldIndex, 1073 heap->false_value()); 1074 proto->InObjectPropertyAtPut(JSRegExp::kMultilineFieldIndex, 1075 heap->false_value()); 1076 proto->InObjectPropertyAtPut(JSRegExp::kLastIndexFieldIndex, 1077 Smi::FromInt(0), 1078 SKIP_WRITE_BARRIER); // It's a Smi. 1079 initial_map->set_prototype(*proto); 1080 factory->SetRegExpIrregexpData(Handle<JSRegExp>::cast(proto), 1081 JSRegExp::IRREGEXP, factory->empty_string(), 1082 JSRegExp::Flags(0), 0); 1083 } 1084 1085 { // -- J S O N 1086 Handle<String> name = factory->InternalizeUtf8String("JSON"); 1087 Handle<JSFunction> cons = factory->NewFunction(name); 1088 JSFunction::SetInstancePrototype(cons, 1089 Handle<Object>(native_context()->initial_object_prototype(), isolate)); 1090 cons->SetInstanceClassName(*name); 1091 Handle<JSObject> json_object = factory->NewJSObject(cons, TENURED); 1092 ASSERT(json_object->IsJSObject()); 1093 JSObject::SetOwnPropertyIgnoreAttributes( 1094 global, name, json_object, DONT_ENUM).Check(); 1095 native_context()->set_json_object(*json_object); 1096 } 1097 1098 { // -- A r r a y B u f f e r 1099 Handle<JSFunction> array_buffer_fun = 1100 InstallFunction( 1101 global, "ArrayBuffer", JS_ARRAY_BUFFER_TYPE, 1102 JSArrayBuffer::kSizeWithInternalFields, 1103 isolate->initial_object_prototype(), 1104 Builtins::kIllegal); 1105 native_context()->set_array_buffer_fun(*array_buffer_fun); 1106 } 1107 1108 { // -- T y p e d A r r a y s 1109 #define INSTALL_TYPED_ARRAY(Type, type, TYPE, ctype, size) \ 1110 { \ 1111 Handle<JSFunction> fun; \ 1112 Handle<Map> external_map; \ 1113 InstallTypedArray(#Type "Array", \ 1114 TYPE##_ELEMENTS, \ 1115 &fun, \ 1116 &external_map); \ 1117 native_context()->set_##type##_array_fun(*fun); \ 1118 native_context()->set_##type##_array_external_map(*external_map); \ 1119 } 1120 TYPED_ARRAYS(INSTALL_TYPED_ARRAY) 1121 #undef INSTALL_TYPED_ARRAY 1122 1123 Handle<JSFunction> data_view_fun = 1124 InstallFunction( 1125 global, "DataView", JS_DATA_VIEW_TYPE, 1126 JSDataView::kSizeWithInternalFields, 1127 isolate->initial_object_prototype(), 1128 Builtins::kIllegal); 1129 native_context()->set_data_view_fun(*data_view_fun); 1130 } 1131 1132 // -- W e a k M a p 1133 InstallFunction(global, "WeakMap", JS_WEAK_MAP_TYPE, JSWeakMap::kSize, 1134 isolate->initial_object_prototype(), Builtins::kIllegal); 1135 // -- W e a k S e t 1136 InstallFunction(global, "WeakSet", JS_WEAK_SET_TYPE, JSWeakSet::kSize, 1137 isolate->initial_object_prototype(), Builtins::kIllegal); 1138 1139 { // --- arguments_boilerplate_ 1140 // Make sure we can recognize argument objects at runtime. 1141 // This is done by introducing an anonymous function with 1142 // class_name equals 'Arguments'. 1143 Handle<String> arguments_string = factory->InternalizeOneByteString( 1144 STATIC_ASCII_VECTOR("Arguments")); 1145 Handle<Code> code(isolate->builtins()->builtin(Builtins::kIllegal)); 1146 1147 Handle<JSFunction> function = factory->NewFunctionWithoutPrototype( 1148 arguments_string, code); 1149 ASSERT(!function->has_initial_map()); 1150 function->shared()->set_instance_class_name(*arguments_string); 1151 function->shared()->set_expected_nof_properties(2); 1152 function->set_prototype_or_initial_map( 1153 native_context()->object_function()->prototype()); 1154 Handle<JSObject> result = factory->NewJSObject(function); 1155 1156 native_context()->set_sloppy_arguments_boilerplate(*result); 1157 // Note: length must be added as the first property and 1158 // callee must be added as the second property. 1159 JSObject::SetOwnPropertyIgnoreAttributes( 1160 result, factory->length_string(), 1161 factory->undefined_value(), DONT_ENUM, 1162 Object::FORCE_TAGGED, FORCE_FIELD).Check(); 1163 JSObject::SetOwnPropertyIgnoreAttributes( 1164 result, factory->callee_string(), 1165 factory->undefined_value(), DONT_ENUM, 1166 Object::FORCE_TAGGED, FORCE_FIELD).Check(); 1167 1168 #ifdef DEBUG 1169 LookupResult lookup(isolate); 1170 result->LookupOwn(factory->callee_string(), &lookup); 1171 ASSERT(lookup.IsField()); 1172 ASSERT(lookup.GetFieldIndex().property_index() == 1173 Heap::kArgumentsCalleeIndex); 1174 1175 result->LookupOwn(factory->length_string(), &lookup); 1176 ASSERT(lookup.IsField()); 1177 ASSERT(lookup.GetFieldIndex().property_index() == 1178 Heap::kArgumentsLengthIndex); 1179 1180 ASSERT(result->map()->inobject_properties() > Heap::kArgumentsCalleeIndex); 1181 ASSERT(result->map()->inobject_properties() > Heap::kArgumentsLengthIndex); 1182 1183 // Check the state of the object. 1184 ASSERT(result->HasFastProperties()); 1185 ASSERT(result->HasFastObjectElements()); 1186 #endif 1187 } 1188 1189 { // --- aliased_arguments_boilerplate_ 1190 // Set up a well-formed parameter map to make assertions happy. 1191 Handle<FixedArray> elements = factory->NewFixedArray(2); 1192 elements->set_map(heap->sloppy_arguments_elements_map()); 1193 Handle<FixedArray> array; 1194 array = factory->NewFixedArray(0); 1195 elements->set(0, *array); 1196 array = factory->NewFixedArray(0); 1197 elements->set(1, *array); 1198 1199 Handle<Map> old_map( 1200 native_context()->sloppy_arguments_boilerplate()->map()); 1201 Handle<Map> new_map = Map::Copy(old_map); 1202 new_map->set_pre_allocated_property_fields(2); 1203 Handle<JSObject> result = factory->NewJSObjectFromMap(new_map); 1204 // Set elements kind after allocating the object because 1205 // NewJSObjectFromMap assumes a fast elements map. 1206 new_map->set_elements_kind(SLOPPY_ARGUMENTS_ELEMENTS); 1207 result->set_elements(*elements); 1208 ASSERT(result->HasSloppyArgumentsElements()); 1209 native_context()->set_aliased_arguments_boilerplate(*result); 1210 } 1211 1212 { // --- strict mode arguments boilerplate 1213 const PropertyAttributes attributes = 1214 static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE | READ_ONLY); 1215 1216 // Create the ThrowTypeError functions. 1217 Handle<AccessorPair> callee = factory->NewAccessorPair(); 1218 Handle<AccessorPair> caller = factory->NewAccessorPair(); 1219 1220 Handle<JSFunction> poison = GetStrictPoisonFunction(); 1221 1222 // Install the ThrowTypeError functions. 1223 callee->set_getter(*poison); 1224 callee->set_setter(*poison); 1225 caller->set_getter(*poison); 1226 caller->set_setter(*poison); 1227 1228 // Create the map. Allocate one in-object field for length. 1229 Handle<Map> map = factory->NewMap(JS_OBJECT_TYPE, 1230 Heap::kStrictArgumentsObjectSize); 1231 // Create the descriptor array for the arguments object. 1232 Map::EnsureDescriptorSlack(map, 3); 1233 1234 { // length 1235 FieldDescriptor d( 1236 factory->length_string(), 0, DONT_ENUM, Representation::Tagged()); 1237 map->AppendDescriptor(&d); 1238 } 1239 { // callee 1240 CallbacksDescriptor d(factory->callee_string(), 1241 callee, 1242 attributes); 1243 map->AppendDescriptor(&d); 1244 } 1245 { // caller 1246 CallbacksDescriptor d(factory->caller_string(), 1247 caller, 1248 attributes); 1249 map->AppendDescriptor(&d); 1250 } 1251 1252 map->set_function_with_prototype(true); 1253 map->set_prototype(native_context()->object_function()->prototype()); 1254 map->set_pre_allocated_property_fields(1); 1255 map->set_inobject_properties(1); 1256 1257 // Copy constructor from the sloppy arguments boilerplate. 1258 map->set_constructor( 1259 native_context()->sloppy_arguments_boilerplate()->map()->constructor()); 1260 1261 // Allocate the arguments boilerplate object. 1262 Handle<JSObject> result = factory->NewJSObjectFromMap(map); 1263 native_context()->set_strict_arguments_boilerplate(*result); 1264 1265 // Add length property only for strict mode boilerplate. 1266 JSObject::SetOwnPropertyIgnoreAttributes( 1267 result, factory->length_string(), 1268 factory->undefined_value(), DONT_ENUM).Check(); 1269 1270 #ifdef DEBUG 1271 LookupResult lookup(isolate); 1272 result->LookupOwn(factory->length_string(), &lookup); 1273 ASSERT(lookup.IsField()); 1274 ASSERT(lookup.GetFieldIndex().property_index() == 1275 Heap::kArgumentsLengthIndex); 1276 1277 ASSERT(result->map()->inobject_properties() > Heap::kArgumentsLengthIndex); 1278 1279 // Check the state of the object. 1280 ASSERT(result->HasFastProperties()); 1281 ASSERT(result->HasFastObjectElements()); 1282 #endif 1283 } 1284 1285 { // --- context extension 1286 // Create a function for the context extension objects. 1287 Handle<Code> code = Handle<Code>( 1288 isolate->builtins()->builtin(Builtins::kIllegal)); 1289 Handle<JSFunction> context_extension_fun = factory->NewFunction( 1290 factory->empty_string(), code, JS_CONTEXT_EXTENSION_OBJECT_TYPE, 1291 JSObject::kHeaderSize); 1292 1293 Handle<String> name = factory->InternalizeOneByteString( 1294 STATIC_ASCII_VECTOR("context_extension")); 1295 context_extension_fun->shared()->set_instance_class_name(*name); 1296 native_context()->set_context_extension_function(*context_extension_fun); 1297 } 1298 1299 1300 { 1301 // Set up the call-as-function delegate. 1302 Handle<Code> code = 1303 Handle<Code>(isolate->builtins()->builtin( 1304 Builtins::kHandleApiCallAsFunction)); 1305 Handle<JSFunction> delegate = factory->NewFunction( 1306 factory->empty_string(), code, JS_OBJECT_TYPE, JSObject::kHeaderSize); 1307 native_context()->set_call_as_function_delegate(*delegate); 1308 delegate->shared()->DontAdaptArguments(); 1309 } 1310 1311 { 1312 // Set up the call-as-constructor delegate. 1313 Handle<Code> code = 1314 Handle<Code>(isolate->builtins()->builtin( 1315 Builtins::kHandleApiCallAsConstructor)); 1316 Handle<JSFunction> delegate = factory->NewFunction( 1317 factory->empty_string(), code, JS_OBJECT_TYPE, JSObject::kHeaderSize); 1318 native_context()->set_call_as_constructor_delegate(*delegate); 1319 delegate->shared()->DontAdaptArguments(); 1320 } 1321 1322 // Initialize the embedder data slot. 1323 Handle<FixedArray> embedder_data = factory->NewFixedArray(3); 1324 native_context()->set_embedder_data(*embedder_data); 1325 } 1326 1327 1328 void Genesis::InstallTypedArray( 1329 const char* name, 1330 ElementsKind elements_kind, 1331 Handle<JSFunction>* fun, 1332 Handle<Map>* external_map) { 1333 Handle<JSObject> global = Handle<JSObject>(native_context()->global_object()); 1334 Handle<JSFunction> result = InstallFunction( 1335 global, name, JS_TYPED_ARRAY_TYPE, JSTypedArray::kSize, 1336 isolate()->initial_object_prototype(), Builtins::kIllegal); 1337 1338 Handle<Map> initial_map = isolate()->factory()->NewMap( 1339 JS_TYPED_ARRAY_TYPE, 1340 JSTypedArray::kSizeWithInternalFields, 1341 elements_kind); 1342 result->set_initial_map(*initial_map); 1343 initial_map->set_constructor(*result); 1344 *fun = result; 1345 1346 ElementsKind external_kind = GetNextTransitionElementsKind(elements_kind); 1347 *external_map = Map::AsElementsKind(initial_map, external_kind); 1348 } 1349 1350 1351 void Genesis::InitializeExperimentalGlobal() { 1352 Handle<JSObject> global = Handle<JSObject>(native_context()->global_object()); 1353 1354 // TODO(mstarzinger): Move this into Genesis::InitializeGlobal once we no 1355 // longer need to live behind flags, so functions get added to the snapshot. 1356 1357 if (FLAG_harmony_symbols) { 1358 // --- S y m b o l --- 1359 Handle<JSFunction> symbol_fun = InstallFunction( 1360 global, "Symbol", JS_VALUE_TYPE, JSValue::kSize, 1361 isolate()->initial_object_prototype(), Builtins::kIllegal); 1362 native_context()->set_symbol_function(*symbol_fun); 1363 } 1364 1365 if (FLAG_harmony_collections) { 1366 // -- M a p 1367 InstallFunction(global, "Map", JS_MAP_TYPE, JSMap::kSize, 1368 isolate()->initial_object_prototype(), Builtins::kIllegal); 1369 // -- S e t 1370 InstallFunction(global, "Set", JS_SET_TYPE, JSSet::kSize, 1371 isolate()->initial_object_prototype(), Builtins::kIllegal); 1372 { // -- S e t I t e r a t o r 1373 Handle<JSObject> builtins(native_context()->builtins()); 1374 Handle<JSFunction> set_iterator_function = 1375 InstallFunction(builtins, "SetIterator", JS_SET_ITERATOR_TYPE, 1376 JSSetIterator::kSize, 1377 isolate()->initial_object_prototype(), 1378 Builtins::kIllegal); 1379 native_context()->set_set_iterator_map( 1380 set_iterator_function->initial_map()); 1381 } 1382 { // -- M a p I t e r a t o r 1383 Handle<JSObject> builtins(native_context()->builtins()); 1384 Handle<JSFunction> map_iterator_function = 1385 InstallFunction(builtins, "MapIterator", JS_MAP_ITERATOR_TYPE, 1386 JSMapIterator::kSize, 1387 isolate()->initial_object_prototype(), 1388 Builtins::kIllegal); 1389 native_context()->set_map_iterator_map( 1390 map_iterator_function->initial_map()); 1391 } 1392 } 1393 1394 if (FLAG_harmony_generators) { 1395 // Create generator meta-objects and install them on the builtins object. 1396 Handle<JSObject> builtins(native_context()->builtins()); 1397 Handle<JSObject> generator_object_prototype = 1398 factory()->NewJSObject(isolate()->object_function(), TENURED); 1399 Handle<JSFunction> generator_function_prototype = InstallFunction( 1400 builtins, "GeneratorFunctionPrototype", JS_FUNCTION_TYPE, 1401 JSFunction::kHeaderSize, generator_object_prototype, 1402 Builtins::kIllegal); 1403 InstallFunction(builtins, "GeneratorFunction", 1404 JS_FUNCTION_TYPE, JSFunction::kSize, 1405 generator_function_prototype, Builtins::kIllegal); 1406 1407 // Create maps for generator functions and their prototypes. Store those 1408 // maps in the native context. 1409 Handle<Map> sloppy_function_map(native_context()->sloppy_function_map()); 1410 Handle<Map> generator_function_map = Map::Copy(sloppy_function_map); 1411 generator_function_map->set_prototype(*generator_function_prototype); 1412 native_context()->set_sloppy_generator_function_map( 1413 *generator_function_map); 1414 1415 // The "arguments" and "caller" instance properties aren't specified, so 1416 // technically we could leave them out. They make even less sense for 1417 // generators than for functions. Still, the same argument that it makes 1418 // sense to keep them around but poisoned in strict mode applies to 1419 // generators as well. With poisoned accessors, naive callers can still 1420 // iterate over the properties without accessing them. 1421 // 1422 // We can't use PoisonArgumentsAndCaller because that mutates accessor pairs 1423 // in place, and the initial state of the generator function map shares the 1424 // accessor pair with sloppy functions. Also the error message should be 1425 // different. Also unhappily, we can't use the API accessors to implement 1426 // poisoning, because API accessors present themselves as data properties, 1427 // not accessor properties, and so getOwnPropertyDescriptor raises an 1428 // exception as it tries to get the values. Sadness. 1429 Handle<AccessorPair> poison_pair(factory()->NewAccessorPair()); 1430 PropertyAttributes rw_attribs = 1431 static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE); 1432 Handle<JSFunction> poison_function = GetGeneratorPoisonFunction(); 1433 poison_pair->set_getter(*poison_function); 1434 poison_pair->set_setter(*poison_function); 1435 ReplaceAccessors(generator_function_map, factory()->arguments_string(), 1436 rw_attribs, poison_pair); 1437 ReplaceAccessors(generator_function_map, factory()->caller_string(), 1438 rw_attribs, poison_pair); 1439 1440 Handle<Map> strict_function_map(native_context()->strict_function_map()); 1441 Handle<Map> strict_generator_function_map = Map::Copy(strict_function_map); 1442 // "arguments" and "caller" already poisoned. 1443 strict_generator_function_map->set_prototype(*generator_function_prototype); 1444 native_context()->set_strict_generator_function_map( 1445 *strict_generator_function_map); 1446 1447 Handle<JSFunction> object_function(native_context()->object_function()); 1448 Handle<Map> generator_object_prototype_map = Map::Create( 1449 object_function, 0); 1450 generator_object_prototype_map->set_prototype( 1451 *generator_object_prototype); 1452 native_context()->set_generator_object_prototype_map( 1453 *generator_object_prototype_map); 1454 } 1455 1456 if (FLAG_harmony_collections || FLAG_harmony_generators) { 1457 // Collection forEach uses an iterator result object. 1458 // Generators return iteraror result objects. 1459 1460 STATIC_ASSERT(JSGeneratorObject::kResultPropertyCount == 2); 1461 Handle<JSFunction> object_function(native_context()->object_function()); 1462 ASSERT(object_function->initial_map()->inobject_properties() == 0); 1463 Handle<Map> iterator_result_map = Map::Create( 1464 object_function, JSGeneratorObject::kResultPropertyCount); 1465 ASSERT(iterator_result_map->inobject_properties() == 1466 JSGeneratorObject::kResultPropertyCount); 1467 Map::EnsureDescriptorSlack( 1468 iterator_result_map, JSGeneratorObject::kResultPropertyCount); 1469 1470 FieldDescriptor value_descr(isolate()->factory()->value_string(), 1471 JSGeneratorObject::kResultValuePropertyIndex, 1472 NONE, 1473 Representation::Tagged()); 1474 iterator_result_map->AppendDescriptor(&value_descr); 1475 1476 FieldDescriptor done_descr(isolate()->factory()->done_string(), 1477 JSGeneratorObject::kResultDonePropertyIndex, 1478 NONE, 1479 Representation::Tagged()); 1480 iterator_result_map->AppendDescriptor(&done_descr); 1481 1482 iterator_result_map->set_unused_property_fields(0); 1483 ASSERT_EQ(JSGeneratorObject::kResultSize, 1484 iterator_result_map->instance_size()); 1485 native_context()->set_iterator_result_map(*iterator_result_map); 1486 } 1487 } 1488 1489 1490 bool Genesis::CompileBuiltin(Isolate* isolate, int index) { 1491 Vector<const char> name = Natives::GetScriptName(index); 1492 Handle<String> source_code = 1493 isolate->bootstrapper()->NativesSourceLookup(index); 1494 return CompileNative(isolate, name, source_code); 1495 } 1496 1497 1498 bool Genesis::CompileExperimentalBuiltin(Isolate* isolate, int index) { 1499 Vector<const char> name = ExperimentalNatives::GetScriptName(index); 1500 Factory* factory = isolate->factory(); 1501 Handle<String> source_code; 1502 ASSIGN_RETURN_ON_EXCEPTION_VALUE( 1503 isolate, source_code, 1504 factory->NewStringFromAscii( 1505 ExperimentalNatives::GetRawScriptSource(index)), 1506 false); 1507 return CompileNative(isolate, name, source_code); 1508 } 1509 1510 1511 bool Genesis::CompileNative(Isolate* isolate, 1512 Vector<const char> name, 1513 Handle<String> source) { 1514 HandleScope scope(isolate); 1515 SuppressDebug compiling_natives(isolate->debug()); 1516 // During genesis, the boilerplate for stack overflow won't work until the 1517 // environment has been at least partially initialized. Add a stack check 1518 // before entering JS code to catch overflow early. 1519 StackLimitCheck check(isolate); 1520 if (check.HasOverflowed()) return false; 1521 1522 bool result = CompileScriptCached(isolate, 1523 name, 1524 source, 1525 NULL, 1526 NULL, 1527 Handle<Context>(isolate->context()), 1528 true); 1529 ASSERT(isolate->has_pending_exception() != result); 1530 if (!result) isolate->clear_pending_exception(); 1531 return result; 1532 } 1533 1534 1535 bool Genesis::CompileScriptCached(Isolate* isolate, 1536 Vector<const char> name, 1537 Handle<String> source, 1538 SourceCodeCache* cache, 1539 v8::Extension* extension, 1540 Handle<Context> top_context, 1541 bool use_runtime_context) { 1542 Factory* factory = isolate->factory(); 1543 HandleScope scope(isolate); 1544 Handle<SharedFunctionInfo> function_info; 1545 1546 // If we can't find the function in the cache, we compile a new 1547 // function and insert it into the cache. 1548 if (cache == NULL || !cache->Lookup(name, &function_info)) { 1549 ASSERT(source->IsOneByteRepresentation()); 1550 Handle<String> script_name = 1551 factory->NewStringFromUtf8(name).ToHandleChecked(); 1552 function_info = Compiler::CompileScript( 1553 source, 1554 script_name, 1555 0, 1556 0, 1557 false, 1558 top_context, 1559 extension, 1560 NULL, 1561 NO_CACHED_DATA, 1562 use_runtime_context ? NATIVES_CODE : NOT_NATIVES_CODE); 1563 if (function_info.is_null()) return false; 1564 if (cache != NULL) cache->Add(name, function_info); 1565 } 1566 1567 // Set up the function context. Conceptually, we should clone the 1568 // function before overwriting the context but since we're in a 1569 // single-threaded environment it is not strictly necessary. 1570 ASSERT(top_context->IsNativeContext()); 1571 Handle<Context> context = 1572 Handle<Context>(use_runtime_context 1573 ? Handle<Context>(top_context->runtime_context()) 1574 : top_context); 1575 Handle<JSFunction> fun = 1576 factory->NewFunctionFromSharedFunctionInfo(function_info, context); 1577 1578 // Call function using either the runtime object or the global 1579 // object as the receiver. Provide no parameters. 1580 Handle<Object> receiver = 1581 Handle<Object>(use_runtime_context 1582 ? top_context->builtins() 1583 : top_context->global_object(), 1584 isolate); 1585 return !Execution::Call( 1586 isolate, fun, receiver, 0, NULL).is_null(); 1587 } 1588 1589 1590 #define INSTALL_NATIVE(Type, name, var) \ 1591 Handle<String> var##_name = \ 1592 factory()->InternalizeOneByteString(STATIC_ASCII_VECTOR(name)); \ 1593 Handle<Object> var##_native = Object::GetProperty( \ 1594 handle(native_context()->builtins()), var##_name).ToHandleChecked(); \ 1595 native_context()->set_##var(Type::cast(*var##_native)); 1596 1597 1598 void Genesis::InstallNativeFunctions() { 1599 HandleScope scope(isolate()); 1600 INSTALL_NATIVE(JSFunction, "CreateDate", create_date_fun); 1601 1602 INSTALL_NATIVE(JSFunction, "ToNumber", to_number_fun); 1603 INSTALL_NATIVE(JSFunction, "ToString", to_string_fun); 1604 INSTALL_NATIVE(JSFunction, "ToDetailString", to_detail_string_fun); 1605 INSTALL_NATIVE(JSFunction, "ToObject", to_object_fun); 1606 INSTALL_NATIVE(JSFunction, "ToInteger", to_integer_fun); 1607 INSTALL_NATIVE(JSFunction, "ToUint32", to_uint32_fun); 1608 INSTALL_NATIVE(JSFunction, "ToInt32", to_int32_fun); 1609 1610 INSTALL_NATIVE(JSFunction, "GlobalEval", global_eval_fun); 1611 INSTALL_NATIVE(JSFunction, "Instantiate", instantiate_fun); 1612 INSTALL_NATIVE(JSFunction, "ConfigureTemplateInstance", 1613 configure_instance_fun); 1614 INSTALL_NATIVE(JSFunction, "GetStackTraceLine", get_stack_trace_line_fun); 1615 INSTALL_NATIVE(JSObject, "functionCache", function_cache); 1616 INSTALL_NATIVE(JSFunction, "ToCompletePropertyDescriptor", 1617 to_complete_property_descriptor); 1618 1619 INSTALL_NATIVE(JSFunction, "IsPromise", is_promise); 1620 INSTALL_NATIVE(JSFunction, "PromiseCreate", promise_create); 1621 INSTALL_NATIVE(JSFunction, "PromiseResolve", promise_resolve); 1622 INSTALL_NATIVE(JSFunction, "PromiseReject", promise_reject); 1623 INSTALL_NATIVE(JSFunction, "PromiseChain", promise_chain); 1624 INSTALL_NATIVE(JSFunction, "PromiseCatch", promise_catch); 1625 INSTALL_NATIVE(JSFunction, "PromiseThen", promise_then); 1626 1627 INSTALL_NATIVE(JSFunction, "NotifyChange", observers_notify_change); 1628 INSTALL_NATIVE(JSFunction, "EnqueueSpliceRecord", observers_enqueue_splice); 1629 INSTALL_NATIVE(JSFunction, "BeginPerformSplice", 1630 observers_begin_perform_splice); 1631 INSTALL_NATIVE(JSFunction, "EndPerformSplice", 1632 observers_end_perform_splice); 1633 INSTALL_NATIVE(JSFunction, "NativeObjectObserve", 1634 native_object_observe); 1635 INSTALL_NATIVE(JSFunction, "NativeObjectGetNotifier", 1636 native_object_get_notifier); 1637 INSTALL_NATIVE(JSFunction, "NativeObjectNotifierPerformChange", 1638 native_object_notifier_perform_change); 1639 } 1640 1641 1642 void Genesis::InstallExperimentalNativeFunctions() { 1643 if (FLAG_harmony_proxies) { 1644 INSTALL_NATIVE(JSFunction, "DerivedHasTrap", derived_has_trap); 1645 INSTALL_NATIVE(JSFunction, "DerivedGetTrap", derived_get_trap); 1646 INSTALL_NATIVE(JSFunction, "DerivedSetTrap", derived_set_trap); 1647 INSTALL_NATIVE(JSFunction, "ProxyEnumerate", proxy_enumerate); 1648 } 1649 1650 if (FLAG_harmony_symbols) { 1651 INSTALL_NATIVE(Symbol, "symbolIterator", iterator_symbol); 1652 } 1653 } 1654 1655 #undef INSTALL_NATIVE 1656 1657 1658 Handle<JSFunction> Genesis::InstallInternalArray( 1659 Handle<JSBuiltinsObject> builtins, 1660 const char* name, 1661 ElementsKind elements_kind) { 1662 // --- I n t e r n a l A r r a y --- 1663 // An array constructor on the builtins object that works like 1664 // the public Array constructor, except that its prototype 1665 // doesn't inherit from Object.prototype. 1666 // To be used only for internal work by builtins. Instances 1667 // must not be leaked to user code. 1668 Handle<JSObject> prototype = 1669 factory()->NewJSObject(isolate()->object_function(), TENURED); 1670 Handle<JSFunction> array_function = InstallFunction( 1671 builtins, name, JS_ARRAY_TYPE, JSArray::kSize, 1672 prototype, Builtins::kInternalArrayCode); 1673 1674 InternalArrayConstructorStub internal_array_constructor_stub(isolate()); 1675 Handle<Code> code = internal_array_constructor_stub.GetCode(); 1676 array_function->shared()->set_construct_stub(*code); 1677 array_function->shared()->DontAdaptArguments(); 1678 1679 Handle<Map> original_map(array_function->initial_map()); 1680 Handle<Map> initial_map = Map::Copy(original_map); 1681 initial_map->set_elements_kind(elements_kind); 1682 array_function->set_initial_map(*initial_map); 1683 1684 // Make "length" magic on instances. 1685 Map::EnsureDescriptorSlack(initial_map, 1); 1686 1687 PropertyAttributes attribs = static_cast<PropertyAttributes>( 1688 DONT_ENUM | DONT_DELETE); 1689 1690 Handle<AccessorInfo> array_length = 1691 Accessors::ArrayLengthInfo(isolate(), attribs); 1692 { // Add length. 1693 CallbacksDescriptor d( 1694 Handle<Name>(Name::cast(array_length->name())), array_length, attribs); 1695 array_function->initial_map()->AppendDescriptor(&d); 1696 } 1697 1698 return array_function; 1699 } 1700 1701 1702 bool Genesis::InstallNatives() { 1703 HandleScope scope(isolate()); 1704 1705 // Create a function for the builtins object. Allocate space for the 1706 // JavaScript builtins, a reference to the builtins object 1707 // (itself) and a reference to the native_context directly in the object. 1708 Handle<Code> code = Handle<Code>( 1709 isolate()->builtins()->builtin(Builtins::kIllegal)); 1710 Handle<JSFunction> builtins_fun = factory()->NewFunction( 1711 factory()->empty_string(), code, JS_BUILTINS_OBJECT_TYPE, 1712 JSBuiltinsObject::kSize); 1713 1714 Handle<String> name = 1715 factory()->InternalizeOneByteString(STATIC_ASCII_VECTOR("builtins")); 1716 builtins_fun->shared()->set_instance_class_name(*name); 1717 builtins_fun->initial_map()->set_dictionary_map(true); 1718 builtins_fun->initial_map()->set_prototype(heap()->null_value()); 1719 1720 // Allocate the builtins object. 1721 Handle<JSBuiltinsObject> builtins = 1722 Handle<JSBuiltinsObject>::cast(factory()->NewGlobalObject(builtins_fun)); 1723 builtins->set_builtins(*builtins); 1724 builtins->set_native_context(*native_context()); 1725 builtins->set_global_context(*native_context()); 1726 builtins->set_global_receiver(*builtins); 1727 builtins->set_global_receiver(native_context()->global_proxy()); 1728 1729 1730 // Set up the 'global' properties of the builtins object. The 1731 // 'global' property that refers to the global object is the only 1732 // way to get from code running in the builtins context to the 1733 // global object. 1734 static const PropertyAttributes attributes = 1735 static_cast<PropertyAttributes>(READ_ONLY | DONT_DELETE); 1736 Handle<String> global_string = 1737 factory()->InternalizeOneByteString(STATIC_ASCII_VECTOR("global")); 1738 Handle<Object> global_obj(native_context()->global_object(), isolate()); 1739 JSObject::SetOwnPropertyIgnoreAttributes( 1740 builtins, global_string, global_obj, attributes).Check(); 1741 Handle<String> builtins_string = 1742 factory()->InternalizeOneByteString(STATIC_ASCII_VECTOR("builtins")); 1743 JSObject::SetOwnPropertyIgnoreAttributes( 1744 builtins, builtins_string, builtins, attributes).Check(); 1745 1746 // Set up the reference from the global object to the builtins object. 1747 JSGlobalObject::cast(native_context()->global_object())-> 1748 set_builtins(*builtins); 1749 1750 // Create a bridge function that has context in the native context. 1751 Handle<JSFunction> bridge = factory()->NewFunction(factory()->empty_string()); 1752 ASSERT(bridge->context() == *isolate()->native_context()); 1753 1754 // Allocate the builtins context. 1755 Handle<Context> context = 1756 factory()->NewFunctionContext(Context::MIN_CONTEXT_SLOTS, bridge); 1757 context->set_global_object(*builtins); // override builtins global object 1758 1759 native_context()->set_runtime_context(*context); 1760 1761 { // -- S c r i p t 1762 // Builtin functions for Script. 1763 Handle<JSFunction> script_fun = InstallFunction( 1764 builtins, "Script", JS_VALUE_TYPE, JSValue::kSize, 1765 isolate()->initial_object_prototype(), Builtins::kIllegal); 1766 Handle<JSObject> prototype = 1767 factory()->NewJSObject(isolate()->object_function(), TENURED); 1768 Accessors::FunctionSetPrototype(script_fun, prototype); 1769 native_context()->set_script_function(*script_fun); 1770 1771 Handle<Map> script_map = Handle<Map>(script_fun->initial_map()); 1772 Map::EnsureDescriptorSlack(script_map, 13); 1773 1774 PropertyAttributes attribs = 1775 static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE | READ_ONLY); 1776 1777 Handle<AccessorInfo> script_column = 1778 Accessors::ScriptColumnOffsetInfo(isolate(), attribs); 1779 { 1780 CallbacksDescriptor d(Handle<Name>(Name::cast(script_column->name())), 1781 script_column, attribs); 1782 script_map->AppendDescriptor(&d); 1783 } 1784 1785 Handle<AccessorInfo> script_id = 1786 Accessors::ScriptIdInfo(isolate(), attribs); 1787 { 1788 CallbacksDescriptor d(Handle<Name>(Name::cast(script_id->name())), 1789 script_id, attribs); 1790 script_map->AppendDescriptor(&d); 1791 } 1792 1793 1794 Handle<AccessorInfo> script_name = 1795 Accessors::ScriptNameInfo(isolate(), attribs); 1796 { 1797 CallbacksDescriptor d(Handle<Name>(Name::cast(script_name->name())), 1798 script_name, attribs); 1799 script_map->AppendDescriptor(&d); 1800 } 1801 1802 Handle<AccessorInfo> script_line = 1803 Accessors::ScriptLineOffsetInfo(isolate(), attribs); 1804 { 1805 CallbacksDescriptor d(Handle<Name>(Name::cast(script_line->name())), 1806 script_line, attribs); 1807 script_map->AppendDescriptor(&d); 1808 } 1809 1810 Handle<AccessorInfo> script_source = 1811 Accessors::ScriptSourceInfo(isolate(), attribs); 1812 { 1813 CallbacksDescriptor d(Handle<Name>(Name::cast(script_source->name())), 1814 script_source, attribs); 1815 script_map->AppendDescriptor(&d); 1816 } 1817 1818 Handle<AccessorInfo> script_type = 1819 Accessors::ScriptTypeInfo(isolate(), attribs); 1820 { 1821 CallbacksDescriptor d(Handle<Name>(Name::cast(script_type->name())), 1822 script_type, attribs); 1823 script_map->AppendDescriptor(&d); 1824 } 1825 1826 Handle<AccessorInfo> script_compilation_type = 1827 Accessors::ScriptCompilationTypeInfo(isolate(), attribs); 1828 { 1829 CallbacksDescriptor d( 1830 Handle<Name>(Name::cast(script_compilation_type->name())), 1831 script_compilation_type, attribs); 1832 script_map->AppendDescriptor(&d); 1833 } 1834 1835 Handle<AccessorInfo> script_line_ends = 1836 Accessors::ScriptLineEndsInfo(isolate(), attribs); 1837 { 1838 CallbacksDescriptor d(Handle<Name>(Name::cast(script_line_ends->name())), 1839 script_line_ends, attribs); 1840 script_map->AppendDescriptor(&d); 1841 } 1842 1843 Handle<AccessorInfo> script_context_data = 1844 Accessors::ScriptContextDataInfo(isolate(), attribs); 1845 { 1846 CallbacksDescriptor d( 1847 Handle<Name>(Name::cast(script_context_data->name())), 1848 script_context_data, attribs); 1849 script_map->AppendDescriptor(&d); 1850 } 1851 1852 Handle<AccessorInfo> script_eval_from_script = 1853 Accessors::ScriptEvalFromScriptInfo(isolate(), attribs); 1854 { 1855 CallbacksDescriptor d( 1856 Handle<Name>(Name::cast(script_eval_from_script->name())), 1857 script_eval_from_script, attribs); 1858 script_map->AppendDescriptor(&d); 1859 } 1860 1861 Handle<AccessorInfo> script_eval_from_script_position = 1862 Accessors::ScriptEvalFromScriptPositionInfo(isolate(), attribs); 1863 { 1864 CallbacksDescriptor d( 1865 Handle<Name>(Name::cast(script_eval_from_script_position->name())), 1866 script_eval_from_script_position, attribs); 1867 script_map->AppendDescriptor(&d); 1868 } 1869 1870 Handle<AccessorInfo> script_eval_from_function_name = 1871 Accessors::ScriptEvalFromFunctionNameInfo(isolate(), attribs); 1872 { 1873 CallbacksDescriptor d( 1874 Handle<Name>(Name::cast(script_eval_from_function_name->name())), 1875 script_eval_from_function_name, attribs); 1876 script_map->AppendDescriptor(&d); 1877 } 1878 1879 // Allocate the empty script. 1880 Handle<Script> script = factory()->NewScript(factory()->empty_string()); 1881 script->set_type(Smi::FromInt(Script::TYPE_NATIVE)); 1882 heap()->public_set_empty_script(*script); 1883 } 1884 { 1885 // Builtin function for OpaqueReference -- a JSValue-based object, 1886 // that keeps its field isolated from JavaScript code. It may store 1887 // objects, that JavaScript code may not access. 1888 Handle<JSFunction> opaque_reference_fun = InstallFunction( 1889 builtins, "OpaqueReference", JS_VALUE_TYPE, JSValue::kSize, 1890 isolate()->initial_object_prototype(), Builtins::kIllegal); 1891 Handle<JSObject> prototype = 1892 factory()->NewJSObject(isolate()->object_function(), TENURED); 1893 Accessors::FunctionSetPrototype(opaque_reference_fun, prototype); 1894 native_context()->set_opaque_reference_function(*opaque_reference_fun); 1895 } 1896 1897 // InternalArrays should not use Smi-Only array optimizations. There are too 1898 // many places in the C++ runtime code (e.g. RegEx) that assume that 1899 // elements in InternalArrays can be set to non-Smi values without going 1900 // through a common bottleneck that would make the SMI_ONLY -> FAST_ELEMENT 1901 // transition easy to trap. Moreover, they rarely are smi-only. 1902 { 1903 Handle<JSFunction> array_function = 1904 InstallInternalArray(builtins, "InternalArray", FAST_HOLEY_ELEMENTS); 1905 native_context()->set_internal_array_function(*array_function); 1906 } 1907 1908 { 1909 InstallInternalArray(builtins, "InternalPackedArray", FAST_ELEMENTS); 1910 } 1911 1912 if (FLAG_disable_native_files) { 1913 PrintF("Warning: Running without installed natives!\n"); 1914 return true; 1915 } 1916 1917 // Install natives. 1918 for (int i = Natives::GetDebuggerCount(); 1919 i < Natives::GetBuiltinsCount(); 1920 i++) { 1921 if (!CompileBuiltin(isolate(), i)) return false; 1922 // TODO(ager): We really only need to install the JS builtin 1923 // functions on the builtins object after compiling and running 1924 // runtime.js. 1925 if (!InstallJSBuiltins(builtins)) return false; 1926 } 1927 1928 InstallNativeFunctions(); 1929 1930 // Store the map for the string prototype after the natives has been compiled 1931 // and the String function has been set up. 1932 Handle<JSFunction> string_function(native_context()->string_function()); 1933 ASSERT(JSObject::cast( 1934 string_function->initial_map()->prototype())->HasFastProperties()); 1935 native_context()->set_string_function_prototype_map( 1936 HeapObject::cast(string_function->initial_map()->prototype())->map()); 1937 1938 // Install Function.prototype.call and apply. 1939 { Handle<String> key = factory()->function_class_string(); 1940 Handle<JSFunction> function = 1941 Handle<JSFunction>::cast(Object::GetProperty( 1942 isolate()->global_object(), key).ToHandleChecked()); 1943 Handle<JSObject> proto = 1944 Handle<JSObject>(JSObject::cast(function->instance_prototype())); 1945 1946 // Install the call and the apply functions. 1947 Handle<JSFunction> call = 1948 InstallFunction(proto, "call", JS_OBJECT_TYPE, JSObject::kHeaderSize, 1949 MaybeHandle<JSObject>(), Builtins::kFunctionCall); 1950 Handle<JSFunction> apply = 1951 InstallFunction(proto, "apply", JS_OBJECT_TYPE, JSObject::kHeaderSize, 1952 MaybeHandle<JSObject>(), Builtins::kFunctionApply); 1953 1954 // Make sure that Function.prototype.call appears to be compiled. 1955 // The code will never be called, but inline caching for call will 1956 // only work if it appears to be compiled. 1957 call->shared()->DontAdaptArguments(); 1958 ASSERT(call->is_compiled()); 1959 1960 // Set the expected parameters for apply to 2; required by builtin. 1961 apply->shared()->set_formal_parameter_count(2); 1962 1963 // Set the lengths for the functions to satisfy ECMA-262. 1964 call->shared()->set_length(1); 1965 apply->shared()->set_length(2); 1966 } 1967 1968 InstallBuiltinFunctionIds(); 1969 1970 // Create a constructor for RegExp results (a variant of Array that 1971 // predefines the two properties index and match). 1972 { 1973 // RegExpResult initial map. 1974 1975 // Find global.Array.prototype to inherit from. 1976 Handle<JSFunction> array_constructor(native_context()->array_function()); 1977 Handle<JSObject> array_prototype( 1978 JSObject::cast(array_constructor->instance_prototype())); 1979 1980 // Add initial map. 1981 Handle<Map> initial_map = 1982 factory()->NewMap(JS_ARRAY_TYPE, JSRegExpResult::kSize); 1983 initial_map->set_constructor(*array_constructor); 1984 1985 // Set prototype on map. 1986 initial_map->set_non_instance_prototype(false); 1987 initial_map->set_prototype(*array_prototype); 1988 1989 // Update map with length accessor from Array and add "index" and "input". 1990 Map::EnsureDescriptorSlack(initial_map, 3); 1991 1992 { 1993 JSFunction* array_function = native_context()->array_function(); 1994 Handle<DescriptorArray> array_descriptors( 1995 array_function->initial_map()->instance_descriptors()); 1996 Handle<String> length = factory()->length_string(); 1997 int old = array_descriptors->SearchWithCache( 1998 *length, array_function->initial_map()); 1999 ASSERT(old != DescriptorArray::kNotFound); 2000 CallbacksDescriptor desc(length, 2001 handle(array_descriptors->GetValue(old), 2002 isolate()), 2003 array_descriptors->GetDetails(old).attributes()); 2004 initial_map->AppendDescriptor(&desc); 2005 } 2006 { 2007 FieldDescriptor index_field(factory()->index_string(), 2008 JSRegExpResult::kIndexIndex, 2009 NONE, 2010 Representation::Tagged()); 2011 initial_map->AppendDescriptor(&index_field); 2012 } 2013 2014 { 2015 FieldDescriptor input_field(factory()->input_string(), 2016 JSRegExpResult::kInputIndex, 2017 NONE, 2018 Representation::Tagged()); 2019 initial_map->AppendDescriptor(&input_field); 2020 } 2021 2022 initial_map->set_inobject_properties(2); 2023 initial_map->set_pre_allocated_property_fields(2); 2024 initial_map->set_unused_property_fields(0); 2025 2026 native_context()->set_regexp_result_map(*initial_map); 2027 } 2028 2029 #ifdef VERIFY_HEAP 2030 builtins->ObjectVerify(); 2031 #endif 2032 2033 return true; 2034 } 2035 2036 2037 #define INSTALL_EXPERIMENTAL_NATIVE(i, flag, file) \ 2038 if (FLAG_harmony_##flag && \ 2039 strcmp(ExperimentalNatives::GetScriptName(i).start(), \ 2040 "native " file) == 0) { \ 2041 if (!CompileExperimentalBuiltin(isolate(), i)) return false; \ 2042 } 2043 2044 2045 bool Genesis::InstallExperimentalNatives() { 2046 for (int i = ExperimentalNatives::GetDebuggerCount(); 2047 i < ExperimentalNatives::GetBuiltinsCount(); 2048 i++) { 2049 INSTALL_EXPERIMENTAL_NATIVE(i, symbols, "symbol.js") 2050 INSTALL_EXPERIMENTAL_NATIVE(i, proxies, "proxy.js") 2051 INSTALL_EXPERIMENTAL_NATIVE(i, collections, "collection.js") 2052 INSTALL_EXPERIMENTAL_NATIVE(i, collections, "collection-iterator.js") 2053 INSTALL_EXPERIMENTAL_NATIVE(i, generators, "generator.js") 2054 INSTALL_EXPERIMENTAL_NATIVE(i, iteration, "array-iterator.js") 2055 INSTALL_EXPERIMENTAL_NATIVE(i, strings, "harmony-string.js") 2056 INSTALL_EXPERIMENTAL_NATIVE(i, arrays, "harmony-array.js") 2057 INSTALL_EXPERIMENTAL_NATIVE(i, maths, "harmony-math.js") 2058 } 2059 2060 InstallExperimentalNativeFunctions(); 2061 InstallExperimentalBuiltinFunctionIds(); 2062 return true; 2063 } 2064 2065 2066 static Handle<JSObject> ResolveBuiltinIdHolder( 2067 Handle<Context> native_context, 2068 const char* holder_expr) { 2069 Isolate* isolate = native_context->GetIsolate(); 2070 Factory* factory = isolate->factory(); 2071 Handle<GlobalObject> global(native_context->global_object()); 2072 const char* period_pos = strchr(holder_expr, '.'); 2073 if (period_pos == NULL) { 2074 return Handle<JSObject>::cast(Object::GetPropertyOrElement( 2075 global, factory->InternalizeUtf8String(holder_expr)).ToHandleChecked()); 2076 } 2077 ASSERT_EQ(".prototype", period_pos); 2078 Vector<const char> property(holder_expr, 2079 static_cast<int>(period_pos - holder_expr)); 2080 Handle<String> property_string = factory->InternalizeUtf8String(property); 2081 ASSERT(!property_string.is_null()); 2082 Handle<JSFunction> function = Handle<JSFunction>::cast( 2083 Object::GetProperty(global, property_string).ToHandleChecked()); 2084 return Handle<JSObject>(JSObject::cast(function->prototype())); 2085 } 2086 2087 2088 static void InstallBuiltinFunctionId(Handle<JSObject> holder, 2089 const char* function_name, 2090 BuiltinFunctionId id) { 2091 Isolate* isolate = holder->GetIsolate(); 2092 Handle<Object> function_object = 2093 Object::GetProperty(isolate, holder, function_name).ToHandleChecked(); 2094 Handle<JSFunction> function = Handle<JSFunction>::cast(function_object); 2095 function->shared()->set_function_data(Smi::FromInt(id)); 2096 } 2097 2098 2099 void Genesis::InstallBuiltinFunctionIds() { 2100 HandleScope scope(isolate()); 2101 #define INSTALL_BUILTIN_ID(holder_expr, fun_name, name) \ 2102 { \ 2103 Handle<JSObject> holder = ResolveBuiltinIdHolder( \ 2104 native_context(), #holder_expr); \ 2105 BuiltinFunctionId id = k##name; \ 2106 InstallBuiltinFunctionId(holder, #fun_name, id); \ 2107 } 2108 FUNCTIONS_WITH_ID_LIST(INSTALL_BUILTIN_ID) 2109 #undef INSTALL_BUILTIN_ID 2110 } 2111 2112 2113 void Genesis::InstallExperimentalBuiltinFunctionIds() { 2114 HandleScope scope(isolate()); 2115 if (FLAG_harmony_maths) { 2116 Handle<JSObject> holder = ResolveBuiltinIdHolder(native_context(), "Math"); 2117 InstallBuiltinFunctionId(holder, "clz32", kMathClz32); 2118 } 2119 } 2120 2121 2122 // Do not forget to update macros.py with named constant 2123 // of cache id. 2124 #define JSFUNCTION_RESULT_CACHE_LIST(F) \ 2125 F(16, native_context()->regexp_function()) 2126 2127 2128 static FixedArray* CreateCache(int size, Handle<JSFunction> factory_function) { 2129 Factory* factory = factory_function->GetIsolate()->factory(); 2130 // Caches are supposed to live for a long time, allocate in old space. 2131 int array_size = JSFunctionResultCache::kEntriesIndex + 2 * size; 2132 // Cannot use cast as object is not fully initialized yet. 2133 JSFunctionResultCache* cache = reinterpret_cast<JSFunctionResultCache*>( 2134 *factory->NewFixedArrayWithHoles(array_size, TENURED)); 2135 cache->set(JSFunctionResultCache::kFactoryIndex, *factory_function); 2136 cache->MakeZeroSize(); 2137 return cache; 2138 } 2139 2140 2141 void Genesis::InstallJSFunctionResultCaches() { 2142 const int kNumberOfCaches = 0 + 2143 #define F(size, func) + 1 2144 JSFUNCTION_RESULT_CACHE_LIST(F) 2145 #undef F 2146 ; 2147 2148 Handle<FixedArray> caches = 2149 factory()->NewFixedArray(kNumberOfCaches, TENURED); 2150 2151 int index = 0; 2152 2153 #define F(size, func) do { \ 2154 FixedArray* cache = CreateCache((size), Handle<JSFunction>(func)); \ 2155 caches->set(index++, cache); \ 2156 } while (false) 2157 2158 JSFUNCTION_RESULT_CACHE_LIST(F); 2159 2160 #undef F 2161 2162 native_context()->set_jsfunction_result_caches(*caches); 2163 } 2164 2165 2166 void Genesis::InitializeNormalizedMapCaches() { 2167 Handle<NormalizedMapCache> cache = NormalizedMapCache::New(isolate()); 2168 native_context()->set_normalized_map_cache(*cache); 2169 } 2170 2171 2172 bool Bootstrapper::InstallExtensions(Handle<Context> native_context, 2173 v8::ExtensionConfiguration* extensions) { 2174 BootstrapperActive active(this); 2175 SaveContext saved_context(isolate_); 2176 isolate_->set_context(*native_context); 2177 return Genesis::InstallExtensions(native_context, extensions) && 2178 Genesis::InstallSpecialObjects(native_context); 2179 } 2180 2181 2182 bool Genesis::InstallSpecialObjects(Handle<Context> native_context) { 2183 Isolate* isolate = native_context->GetIsolate(); 2184 Factory* factory = isolate->factory(); 2185 HandleScope scope(isolate); 2186 Handle<JSGlobalObject> global(JSGlobalObject::cast( 2187 native_context->global_object())); 2188 // Expose the natives in global if a name for it is specified. 2189 if (FLAG_expose_natives_as != NULL && strlen(FLAG_expose_natives_as) != 0) { 2190 Handle<String> natives = 2191 factory->InternalizeUtf8String(FLAG_expose_natives_as); 2192 RETURN_ON_EXCEPTION_VALUE( 2193 isolate, 2194 JSObject::SetOwnPropertyIgnoreAttributes( 2195 global, natives, Handle<JSObject>(global->builtins()), DONT_ENUM), 2196 false); 2197 } 2198 2199 Handle<Object> Error = Object::GetProperty( 2200 isolate, global, "Error").ToHandleChecked(); 2201 if (Error->IsJSObject()) { 2202 Handle<String> name = factory->InternalizeOneByteString( 2203 STATIC_ASCII_VECTOR("stackTraceLimit")); 2204 Handle<Smi> stack_trace_limit( 2205 Smi::FromInt(FLAG_stack_trace_limit), isolate); 2206 RETURN_ON_EXCEPTION_VALUE( 2207 isolate, 2208 JSObject::SetOwnPropertyIgnoreAttributes( 2209 Handle<JSObject>::cast(Error), name, stack_trace_limit, NONE), 2210 false); 2211 } 2212 2213 // Expose the debug global object in global if a name for it is specified. 2214 if (FLAG_expose_debug_as != NULL && strlen(FLAG_expose_debug_as) != 0) { 2215 // If loading fails we just bail out without installing the 2216 // debugger but without tanking the whole context. 2217 Debug* debug = isolate->debug(); 2218 if (!debug->Load()) return true; 2219 Handle<Context> debug_context = debug->debug_context(); 2220 // Set the security token for the debugger context to the same as 2221 // the shell native context to allow calling between these (otherwise 2222 // exposing debug global object doesn't make much sense). 2223 debug_context->set_security_token(native_context->security_token()); 2224 Handle<String> debug_string = 2225 factory->InternalizeUtf8String(FLAG_expose_debug_as); 2226 Handle<Object> global_proxy(debug_context->global_proxy(), isolate); 2227 RETURN_ON_EXCEPTION_VALUE( 2228 isolate, 2229 JSObject::SetOwnPropertyIgnoreAttributes( 2230 global, debug_string, global_proxy, DONT_ENUM), 2231 false); 2232 } 2233 return true; 2234 } 2235 2236 2237 static uint32_t Hash(RegisteredExtension* extension) { 2238 return v8::internal::ComputePointerHash(extension); 2239 } 2240 2241 2242 Genesis::ExtensionStates::ExtensionStates() : map_(HashMap::PointersMatch, 8) {} 2243 2244 Genesis::ExtensionTraversalState Genesis::ExtensionStates::get_state( 2245 RegisteredExtension* extension) { 2246 i::HashMap::Entry* entry = map_.Lookup(extension, Hash(extension), false); 2247 if (entry == NULL) { 2248 return UNVISITED; 2249 } 2250 return static_cast<ExtensionTraversalState>( 2251 reinterpret_cast<intptr_t>(entry->value)); 2252 } 2253 2254 void Genesis::ExtensionStates::set_state(RegisteredExtension* extension, 2255 ExtensionTraversalState state) { 2256 map_.Lookup(extension, Hash(extension), true)->value = 2257 reinterpret_cast<void*>(static_cast<intptr_t>(state)); 2258 } 2259 2260 2261 bool Genesis::InstallExtensions(Handle<Context> native_context, 2262 v8::ExtensionConfiguration* extensions) { 2263 Isolate* isolate = native_context->GetIsolate(); 2264 ExtensionStates extension_states; // All extensions have state UNVISITED. 2265 return InstallAutoExtensions(isolate, &extension_states) && 2266 (!FLAG_expose_free_buffer || 2267 InstallExtension(isolate, "v8/free-buffer", &extension_states)) && 2268 (!FLAG_expose_gc || 2269 InstallExtension(isolate, "v8/gc", &extension_states)) && 2270 (!FLAG_expose_externalize_string || 2271 InstallExtension(isolate, "v8/externalize", &extension_states)) && 2272 (!FLAG_track_gc_object_stats || 2273 InstallExtension(isolate, "v8/statistics", &extension_states)) && 2274 (!FLAG_expose_trigger_failure || 2275 InstallExtension(isolate, "v8/trigger-failure", &extension_states)) && 2276 InstallRequestedExtensions(isolate, extensions, &extension_states); 2277 } 2278 2279 2280 bool Genesis::InstallAutoExtensions(Isolate* isolate, 2281 ExtensionStates* extension_states) { 2282 for (v8::RegisteredExtension* it = v8::RegisteredExtension::first_extension(); 2283 it != NULL; 2284 it = it->next()) { 2285 if (it->extension()->auto_enable() && 2286 !InstallExtension(isolate, it, extension_states)) { 2287 return false; 2288 } 2289 } 2290 return true; 2291 } 2292 2293 2294 bool Genesis::InstallRequestedExtensions(Isolate* isolate, 2295 v8::ExtensionConfiguration* extensions, 2296 ExtensionStates* extension_states) { 2297 for (const char** it = extensions->begin(); it != extensions->end(); ++it) { 2298 if (!InstallExtension(isolate, *it, extension_states)) return false; 2299 } 2300 return true; 2301 } 2302 2303 2304 // Installs a named extension. This methods is unoptimized and does 2305 // not scale well if we want to support a large number of extensions. 2306 bool Genesis::InstallExtension(Isolate* isolate, 2307 const char* name, 2308 ExtensionStates* extension_states) { 2309 for (v8::RegisteredExtension* it = v8::RegisteredExtension::first_extension(); 2310 it != NULL; 2311 it = it->next()) { 2312 if (strcmp(name, it->extension()->name()) == 0) { 2313 return InstallExtension(isolate, it, extension_states); 2314 } 2315 } 2316 return Utils::ApiCheck(false, 2317 "v8::Context::New()", 2318 "Cannot find required extension"); 2319 } 2320 2321 2322 bool Genesis::InstallExtension(Isolate* isolate, 2323 v8::RegisteredExtension* current, 2324 ExtensionStates* extension_states) { 2325 HandleScope scope(isolate); 2326 2327 if (extension_states->get_state(current) == INSTALLED) return true; 2328 // The current node has already been visited so there must be a 2329 // cycle in the dependency graph; fail. 2330 if (!Utils::ApiCheck(extension_states->get_state(current) != VISITED, 2331 "v8::Context::New()", 2332 "Circular extension dependency")) { 2333 return false; 2334 } 2335 ASSERT(extension_states->get_state(current) == UNVISITED); 2336 extension_states->set_state(current, VISITED); 2337 v8::Extension* extension = current->extension(); 2338 // Install the extension's dependencies 2339 for (int i = 0; i < extension->dependency_count(); i++) { 2340 if (!InstallExtension(isolate, 2341 extension->dependencies()[i], 2342 extension_states)) { 2343 return false; 2344 } 2345 } 2346 // We do not expect this to throw an exception. Change this if it does. 2347 Handle<String> source_code = 2348 isolate->factory()->NewExternalStringFromAscii( 2349 extension->source()).ToHandleChecked(); 2350 bool result = CompileScriptCached(isolate, 2351 CStrVector(extension->name()), 2352 source_code, 2353 isolate->bootstrapper()->extensions_cache(), 2354 extension, 2355 Handle<Context>(isolate->context()), 2356 false); 2357 ASSERT(isolate->has_pending_exception() != result); 2358 if (!result) { 2359 // We print out the name of the extension that fail to install. 2360 // When an error is thrown during bootstrapping we automatically print 2361 // the line number at which this happened to the console in the isolate 2362 // error throwing functionality. 2363 OS::PrintError("Error installing extension '%s'.\n", 2364 current->extension()->name()); 2365 isolate->clear_pending_exception(); 2366 } 2367 extension_states->set_state(current, INSTALLED); 2368 isolate->NotifyExtensionInstalled(); 2369 return result; 2370 } 2371 2372 2373 bool Genesis::InstallJSBuiltins(Handle<JSBuiltinsObject> builtins) { 2374 HandleScope scope(isolate()); 2375 for (int i = 0; i < Builtins::NumberOfJavaScriptBuiltins(); i++) { 2376 Builtins::JavaScript id = static_cast<Builtins::JavaScript>(i); 2377 Handle<Object> function_object = Object::GetProperty( 2378 isolate(), builtins, Builtins::GetName(id)).ToHandleChecked(); 2379 Handle<JSFunction> function = Handle<JSFunction>::cast(function_object); 2380 builtins->set_javascript_builtin(id, *function); 2381 if (!Compiler::EnsureCompiled(function, CLEAR_EXCEPTION)) { 2382 return false; 2383 } 2384 builtins->set_javascript_builtin_code(id, function->shared()->code()); 2385 } 2386 return true; 2387 } 2388 2389 2390 bool Genesis::ConfigureGlobalObjects( 2391 v8::Handle<v8::ObjectTemplate> global_proxy_template) { 2392 Handle<JSObject> global_proxy( 2393 JSObject::cast(native_context()->global_proxy())); 2394 Handle<JSObject> inner_global( 2395 JSObject::cast(native_context()->global_object())); 2396 2397 if (!global_proxy_template.IsEmpty()) { 2398 // Configure the global proxy object. 2399 Handle<ObjectTemplateInfo> proxy_data = 2400 v8::Utils::OpenHandle(*global_proxy_template); 2401 if (!ConfigureApiObject(global_proxy, proxy_data)) return false; 2402 2403 // Configure the inner global object. 2404 Handle<FunctionTemplateInfo> proxy_constructor( 2405 FunctionTemplateInfo::cast(proxy_data->constructor())); 2406 if (!proxy_constructor->prototype_template()->IsUndefined()) { 2407 Handle<ObjectTemplateInfo> inner_data( 2408 ObjectTemplateInfo::cast(proxy_constructor->prototype_template())); 2409 if (!ConfigureApiObject(inner_global, inner_data)) return false; 2410 } 2411 } 2412 2413 SetObjectPrototype(global_proxy, inner_global); 2414 2415 native_context()->set_initial_array_prototype( 2416 JSArray::cast(native_context()->array_function()->prototype())); 2417 2418 return true; 2419 } 2420 2421 2422 bool Genesis::ConfigureApiObject(Handle<JSObject> object, 2423 Handle<ObjectTemplateInfo> object_template) { 2424 ASSERT(!object_template.is_null()); 2425 ASSERT(FunctionTemplateInfo::cast(object_template->constructor()) 2426 ->IsTemplateFor(object->map()));; 2427 2428 MaybeHandle<JSObject> maybe_obj = 2429 Execution::InstantiateObject(object_template); 2430 Handle<JSObject> obj; 2431 if (!maybe_obj.ToHandle(&obj)) { 2432 ASSERT(isolate()->has_pending_exception()); 2433 isolate()->clear_pending_exception(); 2434 return false; 2435 } 2436 TransferObject(obj, object); 2437 return true; 2438 } 2439 2440 2441 void Genesis::TransferNamedProperties(Handle<JSObject> from, 2442 Handle<JSObject> to) { 2443 if (from->HasFastProperties()) { 2444 Handle<DescriptorArray> descs = 2445 Handle<DescriptorArray>(from->map()->instance_descriptors()); 2446 for (int i = 0; i < from->map()->NumberOfOwnDescriptors(); i++) { 2447 PropertyDetails details = descs->GetDetails(i); 2448 switch (details.type()) { 2449 case FIELD: { 2450 HandleScope inner(isolate()); 2451 Handle<Name> key = Handle<Name>(descs->GetKey(i)); 2452 FieldIndex index = FieldIndex::ForDescriptor(from->map(), i); 2453 ASSERT(!descs->GetDetails(i).representation().IsDouble()); 2454 Handle<Object> value = Handle<Object>(from->RawFastPropertyAt(index), 2455 isolate()); 2456 JSObject::SetOwnPropertyIgnoreAttributes( 2457 to, key, value, details.attributes()).Check(); 2458 break; 2459 } 2460 case CONSTANT: { 2461 HandleScope inner(isolate()); 2462 Handle<Name> key = Handle<Name>(descs->GetKey(i)); 2463 Handle<Object> constant(descs->GetConstant(i), isolate()); 2464 JSObject::SetOwnPropertyIgnoreAttributes( 2465 to, key, constant, details.attributes()).Check(); 2466 break; 2467 } 2468 case CALLBACKS: { 2469 LookupResult result(isolate()); 2470 Handle<Name> key(Name::cast(descs->GetKey(i)), isolate()); 2471 to->LookupOwn(key, &result); 2472 // If the property is already there we skip it 2473 if (result.IsFound()) continue; 2474 HandleScope inner(isolate()); 2475 ASSERT(!to->HasFastProperties()); 2476 // Add to dictionary. 2477 Handle<Object> callbacks(descs->GetCallbacksObject(i), isolate()); 2478 PropertyDetails d = PropertyDetails( 2479 details.attributes(), CALLBACKS, i + 1); 2480 JSObject::SetNormalizedProperty(to, key, callbacks, d); 2481 break; 2482 } 2483 case NORMAL: 2484 // Do not occur since the from object has fast properties. 2485 case HANDLER: 2486 case INTERCEPTOR: 2487 case NONEXISTENT: 2488 // No element in instance descriptors have proxy or interceptor type. 2489 UNREACHABLE(); 2490 break; 2491 } 2492 } 2493 } else { 2494 Handle<NameDictionary> properties = 2495 Handle<NameDictionary>(from->property_dictionary()); 2496 int capacity = properties->Capacity(); 2497 for (int i = 0; i < capacity; i++) { 2498 Object* raw_key(properties->KeyAt(i)); 2499 if (properties->IsKey(raw_key)) { 2500 ASSERT(raw_key->IsName()); 2501 // If the property is already there we skip it. 2502 LookupResult result(isolate()); 2503 Handle<Name> key(Name::cast(raw_key)); 2504 to->LookupOwn(key, &result); 2505 if (result.IsFound()) continue; 2506 // Set the property. 2507 Handle<Object> value = Handle<Object>(properties->ValueAt(i), 2508 isolate()); 2509 ASSERT(!value->IsCell()); 2510 if (value->IsPropertyCell()) { 2511 value = Handle<Object>(PropertyCell::cast(*value)->value(), 2512 isolate()); 2513 } 2514 PropertyDetails details = properties->DetailsAt(i); 2515 JSObject::SetOwnPropertyIgnoreAttributes( 2516 to, key, value, details.attributes()).Check(); 2517 } 2518 } 2519 } 2520 } 2521 2522 2523 void Genesis::TransferIndexedProperties(Handle<JSObject> from, 2524 Handle<JSObject> to) { 2525 // Cloning the elements array is sufficient. 2526 Handle<FixedArray> from_elements = 2527 Handle<FixedArray>(FixedArray::cast(from->elements())); 2528 Handle<FixedArray> to_elements = factory()->CopyFixedArray(from_elements); 2529 to->set_elements(*to_elements); 2530 } 2531 2532 2533 void Genesis::TransferObject(Handle<JSObject> from, Handle<JSObject> to) { 2534 HandleScope outer(isolate()); 2535 2536 ASSERT(!from->IsJSArray()); 2537 ASSERT(!to->IsJSArray()); 2538 2539 TransferNamedProperties(from, to); 2540 TransferIndexedProperties(from, to); 2541 2542 // Transfer the prototype (new map is needed). 2543 Handle<Map> old_to_map = Handle<Map>(to->map()); 2544 Handle<Map> new_to_map = Map::Copy(old_to_map); 2545 new_to_map->set_prototype(from->map()->prototype()); 2546 to->set_map(*new_to_map); 2547 } 2548 2549 2550 void Genesis::MakeFunctionInstancePrototypeWritable() { 2551 // The maps with writable prototype are created in CreateEmptyFunction 2552 // and CreateStrictModeFunctionMaps respectively. Initially the maps are 2553 // created with read-only prototype for JS builtins processing. 2554 ASSERT(!sloppy_function_map_writable_prototype_.is_null()); 2555 ASSERT(!strict_function_map_writable_prototype_.is_null()); 2556 2557 // Replace function instance maps to make prototype writable. 2558 native_context()->set_sloppy_function_map( 2559 *sloppy_function_map_writable_prototype_); 2560 native_context()->set_strict_function_map( 2561 *strict_function_map_writable_prototype_); 2562 } 2563 2564 2565 class NoTrackDoubleFieldsForSerializerScope { 2566 public: 2567 explicit NoTrackDoubleFieldsForSerializerScope(Isolate* isolate) 2568 : flag_(FLAG_track_double_fields) { 2569 if (isolate->serializer_enabled()) { 2570 // Disable tracking double fields because heap numbers treated as 2571 // immutable by the serializer. 2572 FLAG_track_double_fields = false; 2573 } 2574 } 2575 2576 ~NoTrackDoubleFieldsForSerializerScope() { 2577 FLAG_track_double_fields = flag_; 2578 } 2579 2580 private: 2581 bool flag_; 2582 }; 2583 2584 2585 Genesis::Genesis(Isolate* isolate, 2586 Handle<Object> global_object, 2587 v8::Handle<v8::ObjectTemplate> global_template, 2588 v8::ExtensionConfiguration* extensions) 2589 : isolate_(isolate), 2590 active_(isolate->bootstrapper()) { 2591 NoTrackDoubleFieldsForSerializerScope disable_scope(isolate); 2592 result_ = Handle<Context>::null(); 2593 // If V8 cannot be initialized, just return. 2594 if (!V8::Initialize(NULL)) return; 2595 2596 // Before creating the roots we must save the context and restore it 2597 // on all function exits. 2598 SaveContext saved_context(isolate); 2599 2600 // During genesis, the boilerplate for stack overflow won't work until the 2601 // environment has been at least partially initialized. Add a stack check 2602 // before entering JS code to catch overflow early. 2603 StackLimitCheck check(isolate); 2604 if (check.HasOverflowed()) return; 2605 2606 // We can only de-serialize a context if the isolate was initialized from 2607 // a snapshot. Otherwise we have to build the context from scratch. 2608 if (isolate->initialized_from_snapshot()) { 2609 native_context_ = Snapshot::NewContextFromSnapshot(isolate); 2610 } else { 2611 native_context_ = Handle<Context>(); 2612 } 2613 2614 if (!native_context().is_null()) { 2615 AddToWeakNativeContextList(*native_context()); 2616 isolate->set_context(*native_context()); 2617 isolate->counters()->contexts_created_by_snapshot()->Increment(); 2618 Handle<GlobalObject> inner_global; 2619 Handle<JSGlobalProxy> global_proxy = 2620 CreateNewGlobals(global_template, 2621 global_object, 2622 &inner_global); 2623 2624 HookUpGlobalProxy(inner_global, global_proxy); 2625 HookUpInnerGlobal(inner_global); 2626 native_context()->builtins()->set_global_receiver( 2627 native_context()->global_proxy()); 2628 2629 if (!ConfigureGlobalObjects(global_template)) return; 2630 } else { 2631 // We get here if there was no context snapshot. 2632 CreateRoots(); 2633 Handle<JSFunction> empty_function = CreateEmptyFunction(isolate); 2634 CreateStrictModeFunctionMaps(empty_function); 2635 Handle<GlobalObject> inner_global; 2636 Handle<JSGlobalProxy> global_proxy = 2637 CreateNewGlobals(global_template, global_object, &inner_global); 2638 HookUpGlobalProxy(inner_global, global_proxy); 2639 InitializeGlobal(inner_global, empty_function); 2640 InstallJSFunctionResultCaches(); 2641 InitializeNormalizedMapCaches(); 2642 if (!InstallNatives()) return; 2643 2644 MakeFunctionInstancePrototypeWritable(); 2645 2646 if (!ConfigureGlobalObjects(global_template)) return; 2647 isolate->counters()->contexts_created_from_scratch()->Increment(); 2648 } 2649 2650 // Initialize experimental globals and install experimental natives. 2651 InitializeExperimentalGlobal(); 2652 if (!InstallExperimentalNatives()) return; 2653 2654 // We can't (de-)serialize typed arrays currently, but we are lucky: The state 2655 // of the random number generator needs no initialization during snapshot 2656 // creation time and we don't need trigonometric functions then. 2657 if (!isolate->serializer_enabled()) { 2658 // Initially seed the per-context random number generator using the 2659 // per-isolate random number generator. 2660 const int num_elems = 2; 2661 const int num_bytes = num_elems * sizeof(uint32_t); 2662 uint32_t* state = reinterpret_cast<uint32_t*>(malloc(num_bytes)); 2663 2664 do { 2665 isolate->random_number_generator()->NextBytes(state, num_bytes); 2666 } while (state[0] == 0 || state[1] == 0); 2667 2668 v8::Local<v8::ArrayBuffer> buffer = v8::ArrayBuffer::New( 2669 reinterpret_cast<v8::Isolate*>(isolate), state, num_bytes); 2670 Utils::OpenHandle(*buffer)->set_should_be_freed(true); 2671 v8::Local<v8::Uint32Array> ta = v8::Uint32Array::New(buffer, 0, num_elems); 2672 Handle<JSBuiltinsObject> builtins(native_context()->builtins()); 2673 Runtime::ForceSetObjectProperty(builtins, 2674 factory()->InternalizeOneByteString( 2675 STATIC_ASCII_VECTOR("rngstate")), 2676 Utils::OpenHandle(*ta), 2677 NONE).Assert(); 2678 2679 // Initialize trigonometric lookup tables and constants. 2680 const int table_num_bytes = TrigonometricLookupTable::table_num_bytes(); 2681 v8::Local<v8::ArrayBuffer> sin_buffer = v8::ArrayBuffer::New( 2682 reinterpret_cast<v8::Isolate*>(isolate), 2683 TrigonometricLookupTable::sin_table(), table_num_bytes); 2684 v8::Local<v8::ArrayBuffer> cos_buffer = v8::ArrayBuffer::New( 2685 reinterpret_cast<v8::Isolate*>(isolate), 2686 TrigonometricLookupTable::cos_x_interval_table(), table_num_bytes); 2687 v8::Local<v8::Float64Array> sin_table = v8::Float64Array::New( 2688 sin_buffer, 0, TrigonometricLookupTable::table_size()); 2689 v8::Local<v8::Float64Array> cos_table = v8::Float64Array::New( 2690 cos_buffer, 0, TrigonometricLookupTable::table_size()); 2691 2692 Runtime::ForceSetObjectProperty(builtins, 2693 factory()->InternalizeOneByteString( 2694 STATIC_ASCII_VECTOR("kSinTable")), 2695 Utils::OpenHandle(*sin_table), 2696 NONE).Assert(); 2697 Runtime::ForceSetObjectProperty( 2698 builtins, 2699 factory()->InternalizeOneByteString( 2700 STATIC_ASCII_VECTOR("kCosXIntervalTable")), 2701 Utils::OpenHandle(*cos_table), 2702 NONE).Assert(); 2703 Runtime::ForceSetObjectProperty( 2704 builtins, 2705 factory()->InternalizeOneByteString( 2706 STATIC_ASCII_VECTOR("kSamples")), 2707 factory()->NewHeapNumber( 2708 TrigonometricLookupTable::samples()), 2709 NONE).Assert(); 2710 Runtime::ForceSetObjectProperty( 2711 builtins, 2712 factory()->InternalizeOneByteString( 2713 STATIC_ASCII_VECTOR("kIndexConvert")), 2714 factory()->NewHeapNumber( 2715 TrigonometricLookupTable::samples_over_pi_half()), 2716 NONE).Assert(); 2717 } 2718 2719 result_ = native_context(); 2720 } 2721 2722 2723 // Support for thread preemption. 2724 2725 // Reserve space for statics needing saving and restoring. 2726 int Bootstrapper::ArchiveSpacePerThread() { 2727 return sizeof(NestingCounterType); 2728 } 2729 2730 2731 // Archive statics that are thread-local. 2732 char* Bootstrapper::ArchiveState(char* to) { 2733 *reinterpret_cast<NestingCounterType*>(to) = nesting_; 2734 nesting_ = 0; 2735 return to + sizeof(NestingCounterType); 2736 } 2737 2738 2739 // Restore statics that are thread-local. 2740 char* Bootstrapper::RestoreState(char* from) { 2741 nesting_ = *reinterpret_cast<NestingCounterType*>(from); 2742 return from + sizeof(NestingCounterType); 2743 } 2744 2745 2746 // Called when the top-level V8 mutex is destroyed. 2747 void Bootstrapper::FreeThreadResources() { 2748 ASSERT(!IsActive()); 2749 } 2750 2751 } } // namespace v8::internal 2752