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