Files
sdk/runtime/vm/bootstrap.cc
T
Regis Crelier 7f57ebcfa1 Remove signature classes from the VM.
They were used as the class of closure instances and as the type class of
function types.
All closure instances now have class _Closure and function types are represented
by a new class FunctionType extending AbstractType.
Fix issue 24567 and add regression test.

R=asiva@google.com, rmacnak@google.com

Review URL: https://codereview.chromium.org/1584223006 .
2016-01-19 16:32:59 -08:00

357 lines
12 KiB
C++

// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#include "vm/bootstrap.h"
#include "include/dart_api.h"
#include "vm/bootstrap_natives.h"
#include "vm/class_finalizer.h"
#include "vm/compiler.h"
#include "vm/dart_api_impl.h"
#include "vm/object.h"
#include "vm/object_store.h"
#include "vm/symbols.h"
namespace dart {
#define INIT_LIBRARY(index, name, source, patch) \
{ index, \
"dart:"#name, source, \
"dart:"#name"-patch", patch } \
typedef struct {
ObjectStore::BootstrapLibraryId index_;
const char* uri_;
const char** source_paths_;
const char* patch_uri_;
const char** patch_paths_;
} bootstrap_lib_props;
enum {
kPathsUriOffset = 0,
kPathsFileOffset = 1,
kPathsSourceOffset = 2,
kPathsEntryLength = 3
};
static bootstrap_lib_props bootstrap_libraries[] = {
INIT_LIBRARY(ObjectStore::kCore,
core,
Bootstrap::core_source_paths_,
Bootstrap::core_patch_paths_),
INIT_LIBRARY(ObjectStore::kAsync,
async,
Bootstrap::async_source_paths_,
Bootstrap::async_patch_paths_),
INIT_LIBRARY(ObjectStore::kConvert,
convert,
Bootstrap::convert_source_paths_,
Bootstrap::convert_patch_paths_),
INIT_LIBRARY(ObjectStore::kCollection,
collection,
Bootstrap::collection_source_paths_,
Bootstrap::collection_patch_paths_),
INIT_LIBRARY(ObjectStore::kDeveloper,
developer,
Bootstrap::developer_source_paths_,
Bootstrap::developer_patch_paths_),
INIT_LIBRARY(ObjectStore::kInternal,
_internal,
Bootstrap::_internal_source_paths_,
Bootstrap::_internal_patch_paths_),
INIT_LIBRARY(ObjectStore::kIsolate,
isolate,
Bootstrap::isolate_source_paths_,
Bootstrap::isolate_patch_paths_),
INIT_LIBRARY(ObjectStore::kMath,
math,
Bootstrap::math_source_paths_,
Bootstrap::math_patch_paths_),
INIT_LIBRARY(ObjectStore::kMirrors,
mirrors,
Bootstrap::mirrors_source_paths_,
Bootstrap::mirrors_patch_paths_),
INIT_LIBRARY(ObjectStore::kProfiler,
profiler,
Bootstrap::profiler_source_paths_,
NULL),
INIT_LIBRARY(ObjectStore::kTypedData,
typed_data,
Bootstrap::typed_data_source_paths_,
Bootstrap::typed_data_patch_paths_),
INIT_LIBRARY(ObjectStore::kVMService,
_vmservice,
Bootstrap::_vmservice_source_paths_,
Bootstrap::_vmservice_patch_paths_),
{ ObjectStore::kNone, NULL, NULL, NULL, NULL }
};
static RawString* GetLibrarySource(const Library& lib,
const String& uri,
bool patch) {
// First check if this is a valid bootstrap library and find it's index
// in the 'bootstrap_libraries' table above.
intptr_t index;
const String& lib_uri = String::Handle(lib.url());
for (index = 0;
bootstrap_libraries[index].index_ != ObjectStore::kNone;
++index) {
if (lib_uri.Equals(bootstrap_libraries[index].uri_)) {
break;
}
}
if (bootstrap_libraries[index].index_ == ObjectStore::kNone) {
return String::null(); // Library is not a bootstrap library.
}
// Try to read the source using the path specified for the uri.
const char** source_paths = patch ?
bootstrap_libraries[index].patch_paths_ :
bootstrap_libraries[index].source_paths_;
if (source_paths == NULL) {
return String::null(); // No path mapping information exists for library.
}
const char* source_path = NULL;
const char* source_data = NULL;
for (intptr_t i = 0; source_paths[i] != NULL; i += kPathsEntryLength) {
if (uri.Equals(source_paths[i + kPathsUriOffset])) {
source_path = source_paths[i + kPathsFileOffset];
source_data = source_paths[i + kPathsSourceOffset];
break;
}
}
if ((source_path == NULL) && (source_data == NULL)) {
return String::null(); // Uri does not exist in path mapping information.
}
const uint8_t* utf8_array = NULL;
intptr_t file_length = -1;
Dart_FileOpenCallback file_open = Isolate::file_open_callback();
Dart_FileReadCallback file_read = Isolate::file_read_callback();
Dart_FileCloseCallback file_close = Isolate::file_close_callback();
if ((file_open != NULL) && (file_read != NULL) && (file_close != NULL)) {
// Try to open and read the file.
void* stream = (*file_open)(source_path, false);
if (stream != NULL) {
(*file_read)(&utf8_array, &file_length, stream);
(*file_close)(stream);
}
}
if (file_length == -1) {
if (source_data != NULL) {
file_length = strlen(source_data);
utf8_array = reinterpret_cast<const uint8_t*>(source_data);
} else {
return String::null();
}
}
ASSERT(utf8_array != NULL);
ASSERT(file_length >= 0);
return String::FromUTF8(utf8_array, file_length);
}
static RawError* Compile(const Library& library, const Script& script) {
bool update_lib_status = (script.kind() == RawScript::kScriptTag ||
script.kind() == RawScript::kLibraryTag);
if (update_lib_status) {
library.SetLoadInProgress();
}
const Error& error = Error::Handle(Compiler::Compile(library, script));
if (update_lib_status) {
if (error.IsNull()) {
library.SetLoaded();
} else {
// Compilation errors are not Dart instances, so just mark the library
// as having failed to load without providing an error instance.
library.SetLoadError(Object::null_instance());
}
}
return error.raw();
}
static Dart_Handle LoadPartSource(Thread* thread,
const Library& lib,
const String& uri) {
Zone* zone = thread->zone();
const String& part_source = String::Handle(
zone, GetLibrarySource(lib, uri, false));
const String& lib_uri = String::Handle(zone, lib.url());
if (part_source.IsNull()) {
return Api::NewError("Unable to read part file '%s' of library '%s'",
uri.ToCString(), lib_uri.ToCString());
}
// Prepend the library URI to form a unique script URI for the part.
const Array& strings = Array::Handle(zone, Array::New(3));
strings.SetAt(0, lib_uri);
strings.SetAt(1, Symbols::Slash());
strings.SetAt(2, uri);
const String& part_uri = String::Handle(zone, String::ConcatAll(strings));
// Create a script object and compile the part.
const Script& part_script = Script::Handle(
zone, Script::New(part_uri, part_source, RawScript::kSourceTag));
const Error& error = Error::Handle(zone, Compile(lib, part_script));
return Api::NewHandle(thread, error.raw());
}
static Dart_Handle BootstrapLibraryTagHandler(Dart_LibraryTag tag,
Dart_Handle library,
Dart_Handle uri) {
Thread* thread = Thread::Current();
Zone* zone = thread->zone();
if (!Dart_IsLibrary(library)) {
return Api::NewError("not a library");
}
if (!Dart_IsString(uri)) {
return Api::NewError("uri is not a string");
}
if (tag == Dart_kCanonicalizeUrl) {
// In the bootstrap loader we do not try and do any canonicalization.
return uri;
}
const String& uri_str = Api::UnwrapStringHandle(zone, uri);
ASSERT(!uri_str.IsNull());
if (tag == Dart_kImportTag) {
// We expect the core bootstrap libraries to only import other
// core bootstrap libraries.
// We have precreated all the bootstrap library objects hence
// we do not expect to be called back with the tag set to kImportTag.
// The bootstrap process explicitly loads all the libraries one by one.
return Api::NewError("Invalid import of '%s' in a bootstrap library",
uri_str.ToCString());
}
ASSERT(tag == Dart_kSourceTag);
const Library& lib = Api::UnwrapLibraryHandle(zone, library);
ASSERT(!lib.IsNull());
return LoadPartSource(thread, lib, uri_str);
}
static RawError* LoadPatchFiles(Zone* zone,
const Library& lib,
const String& patch_uri,
const char** patch_files) {
String& patch_file_uri = String::Handle(zone);
String& source = String::Handle(zone);
Script& script = Script::Handle(zone);
Error& error = Error::Handle(zone);
const Array& strings = Array::Handle(zone, Array::New(3));
strings.SetAt(0, patch_uri);
strings.SetAt(1, Symbols::Slash());
for (intptr_t j = 0; patch_files[j] != NULL; j += kPathsEntryLength) {
patch_file_uri = String::New(patch_files[j + kPathsUriOffset]);
source = GetLibrarySource(lib, patch_file_uri, true);
if (source.IsNull()) {
const String& message = String::Handle(
String::NewFormatted("Unable to find dart patch source for %s",
patch_file_uri.ToCString()));
return ApiError::New(message);
}
// Prepend the patch library URI to form a unique script URI for the patch.
strings.SetAt(2, patch_file_uri);
patch_file_uri = String::ConcatAll(strings);
script = Script::New(patch_file_uri, source, RawScript::kPatchTag);
error = lib.Patch(script);
if (!error.IsNull()) {
return error.raw();
}
}
return Error::null();
}
RawError* Bootstrap::LoadandCompileScripts() {
Thread* thread = Thread::Current();
Isolate* isolate = thread->isolate();
Zone* zone = thread->zone();
String& uri = String::Handle(zone);
String& patch_uri = String::Handle(zone);
String& source = String::Handle(zone);
Script& script = Script::Handle(zone);
Library& lib = Library::Handle(zone);
Error& error = Error::Handle(zone);
Dart_LibraryTagHandler saved_tag_handler = isolate->library_tag_handler();
// Set the library tag handler for the isolate to the bootstrap
// library tag handler so that we can load all the bootstrap libraries.
isolate->set_library_tag_handler(BootstrapLibraryTagHandler);
HANDLESCOPE(thread);
// Create library objects for all the bootstrap libraries.
for (intptr_t i = 0;
bootstrap_libraries[i].index_ != ObjectStore::kNone;
++i) {
uri = Symbols::New(bootstrap_libraries[i].uri_);
lib = Library::LookupLibrary(uri);
if (lib.IsNull()) {
lib = Library::NewLibraryHelper(uri, false);
lib.SetLoadRequested();
lib.Register();
}
isolate->object_store()->set_bootstrap_library(
bootstrap_libraries[i].index_, lib);
}
// Load, compile and patch bootstrap libraries.
for (intptr_t i = 0;
bootstrap_libraries[i].index_ != ObjectStore::kNone;
++i) {
uri = Symbols::New(bootstrap_libraries[i].uri_);
lib = Library::LookupLibrary(uri);
ASSERT(!lib.IsNull());
source = GetLibrarySource(lib, uri, false);
if (source.IsNull()) {
const String& message = String::Handle(
String::NewFormatted("Unable to find dart source for %s",
uri.ToCString()));
error ^= ApiError::New(message);
break;
}
script = Script::New(uri, source, RawScript::kLibraryTag);
error = Compile(lib, script);
if (!error.IsNull()) {
break;
}
// If a patch exists, load and patch the script.
if (bootstrap_libraries[i].patch_paths_ != NULL) {
patch_uri = Symbols::New(bootstrap_libraries[i].patch_uri_);
error = LoadPatchFiles(zone,
lib,
patch_uri,
bootstrap_libraries[i].patch_paths_);
if (!error.IsNull()) {
break;
}
}
}
if (error.IsNull()) {
SetupNativeResolver();
ClassFinalizer::ProcessPendingClasses();
// Eagerly compile the _Closure class as it is the class of all closure
// instances. This allows us to just finalize function types
// without going through the hoops of trying to compile their scope class.
const Class& cls =
Class::Handle(zone, isolate->object_store()->closure_class());
Compiler::CompileClass(cls);
}
// Restore the library tag handler for the isolate.
isolate->set_library_tag_handler(saved_tag_handler);
return error.raw();
}
} // namespace dart