📄 bootstrapper.cc.svn-base
字号:
// Expose the natives in global if a name for it is specified. if (FLAG_expose_natives_as != NULL && strlen(FLAG_expose_natives_as) != 0) { Handle<String> natives_string = Factory::LookupAsciiSymbol(FLAG_expose_natives_as); SetProperty(global, natives_string, Handle<JSObject>(global->builtins()), DONT_ENUM); } // Expose the debug global object in global if a name for it is specified. if (FLAG_expose_debug_as != NULL && strlen(FLAG_expose_debug_as) != 0) { // If loading fails we just bail out without installing the // debugger but without tanking the whole context. if (!Debug::Load()) return true; Handle<JSGlobalObject> debug_global = Handle<JSGlobalObject>( JSGlobalObject::cast(Debug::debug_context()->global())); Handle<String> debug_string = Factory::LookupAsciiSymbol(FLAG_expose_debug_as); SetProperty(global, debug_string, Handle<JSObject>(debug_global), DONT_ENUM); // Set the security token for the debugger global object to the same as // the shell global object to allow calling between these (otherwise // exposing debug global object doesn't make much sense). debug_global->set_security_token(global->security_token()); } return true;}bool Genesis::InstallExtensions(v8::ExtensionConfiguration* extensions) { // Clear coloring of extension list v8::RegisteredExtension* current = v8::RegisteredExtension::first_extension(); while (current != NULL) { current->set_state(v8::UNVISITED); current = current->next(); } // Install auto extensions current = v8::RegisteredExtension::first_extension(); while (current != NULL) { if (current->extension()->auto_enable()) InstallExtension(current); current = current->next(); } if (FLAG_expose_gc) InstallExtension("v8/gc"); if (extensions == NULL) return true; // Install required extensions int count = v8::ImplementationUtilities::GetNameCount(extensions); const char** names = v8::ImplementationUtilities::GetNames(extensions); for (int i = 0; i < count; i++) { if (!InstallExtension(names[i])) return false; } return true;}// Installs a named extension. This methods is unoptimized and does// not scale well if we want to support a large number of extensions.bool Genesis::InstallExtension(const char* name) { v8::RegisteredExtension* current = v8::RegisteredExtension::first_extension(); // Loop until we find the relevant extension while (current != NULL) { if (strcmp(name, current->extension()->name()) == 0) break; current = current->next(); } // Didn't find the extension; fail. if (current == NULL) { v8::Utils::ReportApiFailure( "v8::Context::New()", "Cannot find required extension"); return false; } return InstallExtension(current);}bool Genesis::InstallExtension(v8::RegisteredExtension* current) { HandleScope scope; if (current->state() == v8::INSTALLED) return true; // The current node has already been visited so there must be a // cycle in the dependency graph; fail. if (current->state() == v8::VISITED) { v8::Utils::ReportApiFailure( "v8::Context::New()", "Circular extension dependency"); return false; } ASSERT(current->state() == v8::UNVISITED); current->set_state(v8::VISITED); v8::Extension* extension = current->extension(); // Install the extension's dependencies for (int i = 0; i < extension->dependency_count(); i++) { if (!InstallExtension(extension->dependencies()[i])) return false; } Vector<const char> source = CStrVector(extension->source()); Handle<String> source_code = Factory::NewStringFromAscii(source); bool result = CompileScriptCached(CStrVector(extension->name()), source_code, &extensions_cache, extension, false); ASSERT(Top::has_pending_exception() != result); if (!result) { Top::clear_pending_exception(); v8::Utils::ReportApiFailure( "v8::Context::New()", "Error installing extension"); } current->set_state(v8::INSTALLED); return result;}bool Genesis::ConfigureGlobalObject( v8::Handle<v8::ObjectTemplate> global_template) { Handle<JSObject> global = Handle<JSObject>(global_context()->global()); if (!global_template.IsEmpty()) { Handle<ObjectTemplateInfo> data = v8::Utils::OpenHandle(*global_template); bool pending_exception = false; Handle<JSObject> obj = Execution::InstantiateObject(data, &pending_exception); if (pending_exception) { ASSERT(Top::has_pending_exception()); Top::clear_pending_exception(); return false; } TransferObject(obj, global); } return true;}void Genesis::TransferNamedProperties(Handle<JSObject> from, Handle<JSObject> to) { if (from->HasFastProperties()) { Handle<DescriptorArray> descs = Handle<DescriptorArray>(from->map()->instance_descriptors()); int offset = 0; while (true) { // Iterating through the descriptors is not gc safe so we have to // store the value in a handle and create a new stream for each entry. DescriptorReader stream(*descs, offset); if (stream.eos()) break; // We have to read out the next offset before we do anything that may // cause a gc, since the DescriptorReader is not gc safe. offset = stream.next_position(); PropertyDetails details = stream.GetDetails(); switch (details.type()) { case FIELD: { HandleScope inner; Handle<String> key = Handle<String>(stream.GetKey()); int index = stream.GetFieldIndex(); Handle<Object> value = Handle<Object>(from->properties()->get(index)); SetProperty(to, key, value, details.attributes()); break; } case CONSTANT_FUNCTION: { HandleScope inner; Handle<String> key = Handle<String>(stream.GetKey()); Handle<JSFunction> fun = Handle<JSFunction>(stream.GetConstantFunction()); SetProperty(to, key, fun, details.attributes()); break; } case CALLBACKS: { LookupResult result; to->LocalLookup(stream.GetKey(), &result); // If the property is already there we skip it if (result.IsValid()) continue; HandleScope inner; Handle<DescriptorArray> inst_descs = Handle<DescriptorArray>(to->map()->instance_descriptors()); Handle<String> key = Handle<String>(stream.GetKey()); Handle<Object> entry = Handle<Object>(stream.GetCallbacksObject()); inst_descs = Factory::CopyAppendProxyDescriptor(inst_descs, key, entry, details.attributes()); to->map()->set_instance_descriptors(*inst_descs); break; } case MAP_TRANSITION: case CONSTANT_TRANSITION: case NULL_DESCRIPTOR: // Ignore non-properties. break; case NORMAL: // Do not occur since the from object has fast properties. case INTERCEPTOR: // No element in instance descriptors have interceptor type. UNREACHABLE(); break; } } } else { Handle<Dictionary> properties = Handle<Dictionary>(from->property_dictionary()); int capacity = properties->Capacity(); for (int i = 0; i < capacity; i++) { Object* raw_key(properties->KeyAt(i)); if (properties->IsKey(raw_key)) { ASSERT(raw_key->IsString()); // If the property is already there we skip it. LookupResult result; to->LocalLookup(String::cast(raw_key), &result); if (result.IsValid()) continue; // Set the property. Handle<String> key = Handle<String>(String::cast(raw_key)); Handle<Object> value = Handle<Object>(properties->ValueAt(i)); PropertyDetails details = properties->DetailsAt(i); SetProperty(to, key, value, details.attributes()); } } }}void Genesis::TransferIndexedProperties(Handle<JSObject> from, Handle<JSObject> to) { // Cloning the elements array is sufficient. Handle<FixedArray> from_elements = Handle<FixedArray>(FixedArray::cast(from->elements())); Handle<FixedArray> to_elements = Factory::CopyFixedArray(from_elements); to->set_elements(*to_elements);}void Genesis::TransferObject(Handle<JSObject> from, Handle<JSObject> to) { HandleScope outer; ASSERT(!from->IsJSArray()); ASSERT(!to->IsJSArray()); TransferNamedProperties(from, to); TransferIndexedProperties(from, to); // Transfer the prototype (new map is needed). Handle<Map> old_to_map = Handle<Map>(to->map()); Handle<Map> new_to_map = Factory::CopyMapDropTransitions(old_to_map); new_to_map->set_prototype(from->map()->prototype()); to->set_map(*new_to_map);}void Genesis::MakeFunctionInstancePrototypeWritable() { // Make a new function map so all future functions // will have settable and enumerable prototype properties. HandleScope scope; Handle<DescriptorArray> function_map_descriptors = ComputeFunctionInstanceDescriptor(false, true); Handle<Map> fm = Factory::CopyMap(Top::function_map()); fm->set_instance_descriptors(*function_map_descriptors); Top::context()->global_context()->set_function_map(*fm);}void Genesis::AddSpecialFunction(Handle<JSObject> prototype, const char* name, Handle<Code> code) { Handle<String> key = Factory::LookupAsciiSymbol(name); Handle<Object> value = Handle<Object>(prototype->GetProperty(*key)); if (value->IsJSFunction()) { Handle<JSFunction> optimized = Factory::NewFunction(key, JS_OBJECT_TYPE, JSObject::kHeaderSize, code, false); optimized->shared()->DontAdaptArguments(); int len = global_context()->special_function_table()->length(); Handle<FixedArray> new_array = Factory::NewFixedArray(len + 3); for (int index = 0; index < len; index++) { new_array->set(index, global_context()->special_function_table()->get(index)); } new_array->set(len+0, *prototype); new_array->set(len+1, *value); new_array->set(len+2, *optimized); global_context()->set_special_function_table(*new_array); }}void Genesis::BuildSpecialFunctionTable() { HandleScope scope; Handle<JSObject> global = Handle<JSObject>(global_context()->global()); // Add special versions for Array.prototype.pop and push. Handle<JSFunction> function = Handle<JSFunction>( JSFunction::cast(global->GetProperty(Heap::Array_symbol()))); Handle<JSObject> prototype = Handle<JSObject>(JSObject::cast(function->prototype())); AddSpecialFunction(prototype, "pop", Handle<Code>(Builtins::builtin(Builtins::ArrayPop))); AddSpecialFunction(prototype, "push", Handle<Code>(Builtins::builtin(Builtins::ArrayPush)));}Genesis::Genesis(Handle<Object> global_object, v8::Handle<v8::ObjectTemplate> global_template, v8::ExtensionConfiguration* extensions) { // Link this genesis object into the stacked genesis chain. This // must be done before any early exits because the deconstructor // will always do unlinking. previous_ = current_; current_ = this; result_ = NULL; // If V8 hasn't been and cannot be initialized, just return. if (!V8::HasBeenSetup() && !V8::Initialize(NULL)) return; // Before creating the roots we must save the context and restore it // on all function exits. HandleScope scope; SaveContext context; CreateRoots(global_template, global_object); if (!InstallNatives()) return; MakeFunctionInstancePrototypeWritable(); BuildSpecialFunctionTable(); if (!ConfigureGlobalObject(global_template)) return; if (!InstallExtensions(extensions)) return; if (!InstallSpecialObjects()) return; result_ = global_context_;}} } // namespace v8::internal
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -