| Index: src/bootstrapper.cc
|
| ===================================================================
|
| --- src/bootstrapper.cc (revision 3427)
|
| +++ src/bootstrapper.cc (working copy)
|
| @@ -91,20 +91,53 @@
|
| DISALLOW_COPY_AND_ASSIGN(SourceCodeCache);
|
| };
|
|
|
| -static SourceCodeCache natives_cache(Script::TYPE_NATIVE);
|
| -static SourceCodeCache extensions_cache(Script::TYPE_EXTENSION);
|
| -// This is for delete, not delete[].
|
| -static List<char*>* delete_these_non_arrays_on_tear_down = NULL;
|
| +class Genesis;
|
|
|
| +class BootstrapperPrivateData {
|
| + public:
|
| + SourceCodeCache natives_cache_;
|
| + SourceCodeCache extensions_cache_;
|
| + Genesis* current_;
|
| + // This is for delete, not delete[].
|
| + List<char*>* delete_these_non_arrays_on_tear_down_;
|
|
|
| + List<Object*> code_;
|
| + List<const char*> name_;
|
| + List<int> pc_;
|
| + List<uint32_t> flags_;
|
| +
|
| + BootstrapperPrivateData()
|
| + :delete_these_non_arrays_on_tear_down_(NULL),
|
| + current_(NULL),
|
| + extensions_cache_(Script::TYPE_EXTENSION),
|
| + natives_cache_(Script::TYPE_NATIVE),
|
| + code_(0),
|
| + name_(0),
|
| + pc_(0),
|
| + flags_(0) {
|
| + }
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(BootstrapperPrivateData);
|
| +};
|
| +
|
| +BootstrapperData::BootstrapperData()
|
| + :private_data_(*new BootstrapperPrivateData()) {
|
| +}
|
| +
|
| +BootstrapperData::~BootstrapperData() {
|
| + delete &private_data_;
|
| +}
|
| +
|
| NativesExternalStringResource::NativesExternalStringResource(const char* source)
|
| : data_(source), length_(StrLength(source)) {
|
| - if (delete_these_non_arrays_on_tear_down == NULL) {
|
| - delete_these_non_arrays_on_tear_down = new List<char*>(2);
|
| + BootstrapperPrivateData& data = v8_context()->bootstrapper_data_.
|
| + private_data_;
|
| + if (data.delete_these_non_arrays_on_tear_down_ == NULL) {
|
| + data.delete_these_non_arrays_on_tear_down_ = new List<char*>(2);
|
| }
|
| // The resources are small objects and we only make a fixed number of
|
| // them, but let's clean them up on exit for neatness.
|
| - delete_these_non_arrays_on_tear_down->
|
| + data.delete_these_non_arrays_on_tear_down_->
|
| Add(reinterpret_cast<char*>(this));
|
| }
|
|
|
| @@ -134,35 +167,41 @@
|
|
|
| bool Bootstrapper::NativesCacheLookup(Vector<const char> name,
|
| Handle<JSFunction>* handle) {
|
| - return natives_cache.Lookup(name, handle);
|
| + return v8_context()->bootstrapper_data_.
|
| + private_data_.natives_cache_.Lookup(name, handle);
|
| }
|
|
|
|
|
| void Bootstrapper::NativesCacheAdd(Vector<const char> name,
|
| Handle<JSFunction> fun) {
|
| - natives_cache.Add(name, fun);
|
| + v8_context()->bootstrapper_data_.
|
| + private_data_.natives_cache_.Add(name, fun);
|
| }
|
|
|
|
|
| void Bootstrapper::Initialize(bool create_heap_objects) {
|
| - natives_cache.Initialize(create_heap_objects);
|
| - extensions_cache.Initialize(create_heap_objects);
|
| + BootstrapperPrivateData& data = v8_context()->bootstrapper_data_.
|
| + private_data_;
|
| + data.natives_cache_.Initialize(create_heap_objects);
|
| + data.extensions_cache_.Initialize(create_heap_objects);
|
| }
|
|
|
|
|
| void Bootstrapper::TearDown() {
|
| - if (delete_these_non_arrays_on_tear_down != NULL) {
|
| - int len = delete_these_non_arrays_on_tear_down->length();
|
| + BootstrapperPrivateData& data = v8_context()->bootstrapper_data_.
|
| + private_data_;
|
| + if (data.delete_these_non_arrays_on_tear_down_ != NULL) {
|
| + int len = data.delete_these_non_arrays_on_tear_down_->length();
|
| ASSERT(len < 20); // Don't use this mechanism for unbounded allocations.
|
| for (int i = 0; i < len; i++) {
|
| - delete delete_these_non_arrays_on_tear_down->at(i);
|
| + delete data.delete_these_non_arrays_on_tear_down_->at(i);
|
| }
|
| - delete delete_these_non_arrays_on_tear_down;
|
| - delete_these_non_arrays_on_tear_down = NULL;
|
| + delete data.delete_these_non_arrays_on_tear_down_;
|
| + data.delete_these_non_arrays_on_tear_down_ = NULL;
|
| }
|
|
|
| - natives_cache.Initialize(false); // Yes, symmetrical
|
| - extensions_cache.Initialize(false);
|
| + data.natives_cache_.Initialize(false); // Yes, symmetrical
|
| + data.extensions_cache_.Initialize(false);
|
| }
|
|
|
|
|
| @@ -178,31 +217,21 @@
|
| static void Iterate(ObjectVisitor* v);
|
|
|
| private:
|
| - static List<Object*> code_;
|
| - static List<const char*> name_;
|
| - static List<int> pc_;
|
| - static List<uint32_t> flags_;
|
| -
|
| static void Clear();
|
| };
|
|
|
| -
|
| -List<Object*> PendingFixups::code_(0);
|
| -List<const char*> PendingFixups::name_(0);
|
| -List<int> PendingFixups::pc_(0);
|
| -List<uint32_t> PendingFixups::flags_(0);
|
| -
|
| -
|
| void PendingFixups::Add(Code* code, MacroAssembler* masm) {
|
| // Note this code is not only called during bootstrapping.
|
| List<MacroAssembler::Unresolved>* unresolved = masm->unresolved();
|
| int n = unresolved->length();
|
| + BootstrapperPrivateData& data = v8_context()->bootstrapper_data_.
|
| + private_data_;
|
| for (int i = 0; i < n; i++) {
|
| const char* name = unresolved->at(i).name;
|
| - code_.Add(code);
|
| - name_.Add(name);
|
| - pc_.Add(unresolved->at(i).pc);
|
| - flags_.Add(unresolved->at(i).flags);
|
| + data.code_.Add(code);
|
| + data.name_.Add(name);
|
| + data.pc_.Add(unresolved->at(i).pc);
|
| + data.flags_.Add(unresolved->at(i).flags);
|
| LOG(StringEvent("unresolved", name));
|
| }
|
| }
|
| @@ -210,12 +239,14 @@
|
|
|
| bool PendingFixups::Process(Handle<JSBuiltinsObject> builtins) {
|
| HandleScope scope;
|
| + BootstrapperPrivateData& data = v8_context()->bootstrapper_data_.
|
| + private_data_;
|
| // NOTE: Extra fixups may be added to the list during the iteration
|
| // due to lazy compilation of functions during the processing. Do not
|
| // cache the result of getting the length of the code list.
|
| - for (int i = 0; i < code_.length(); i++) {
|
| - const char* name = name_[i];
|
| - uint32_t flags = flags_[i];
|
| + for (int i = 0; i < data.code_.length(); i++) {
|
| + const char* name = data.name_[i];
|
| + uint32_t flags = data.flags_[i];
|
| Handle<String> symbol = Factory::LookupAsciiSymbol(name);
|
| Object* o = builtins->GetProperty(*symbol);
|
| #ifdef DEBUG
|
| @@ -235,8 +266,8 @@
|
| return false;
|
| }
|
| }
|
| - Code* code = Code::cast(code_[i]);
|
| - Address pc = code->instruction_start() + pc_[i];
|
| + Code* code = Code::cast(data.code_[i]);
|
| + Address pc = code->instruction_start() + data.pc_[i];
|
| RelocInfo target(pc, RelocInfo::CODE_TARGET, 0);
|
| bool use_code_object = Bootstrapper::FixupFlagsUseCodeObject::decode(flags);
|
| if (use_code_object) {
|
| @@ -264,16 +295,20 @@
|
|
|
|
|
| void PendingFixups::Clear() {
|
| - code_.Clear();
|
| - name_.Clear();
|
| - pc_.Clear();
|
| - flags_.Clear();
|
| + BootstrapperPrivateData& data = v8_context()->bootstrapper_data_.
|
| + private_data_;
|
| + data.code_.Clear();
|
| + data.name_.Clear();
|
| + data.pc_.Clear();
|
| + data.flags_.Clear();
|
| }
|
|
|
|
|
| void PendingFixups::Iterate(ObjectVisitor* v) {
|
| - if (!code_.is_empty()) {
|
| - v->VisitPointers(&code_[0], &code_[0] + code_.length());
|
| + BootstrapperPrivateData& data = v8_context()->bootstrapper_data_.
|
| + private_data_;
|
| + if (!data.code_.is_empty()) {
|
| + v->VisitPointers(&data.code_[0], &data.code_[0] + data.code_.length());
|
| }
|
| }
|
|
|
| @@ -288,7 +323,9 @@
|
| Handle<Context> result() { return result_; }
|
|
|
| Genesis* previous() { return previous_; }
|
| - static Genesis* current() { return current_; }
|
| + static Genesis* current() {
|
| + return v8_context()->bootstrapper_data_.private_data_.current_;
|
| + }
|
|
|
| // Support for thread preemption.
|
| static int ArchiveSpacePerThread();
|
| @@ -302,7 +339,6 @@
|
| // triggered during environment creation there may be weak handle
|
| // processing callbacks which may create new environments.
|
| Genesis* previous_;
|
| - static Genesis* current_;
|
|
|
| Handle<Context> global_context() { return global_context_; }
|
|
|
| @@ -347,13 +383,14 @@
|
| Handle<Context> result_;
|
| };
|
|
|
| -Genesis* Genesis::current_ = NULL;
|
|
|
|
|
| void Bootstrapper::Iterate(ObjectVisitor* v) {
|
| - natives_cache.Iterate(v);
|
| + BootstrapperPrivateData& data = v8_context()->bootstrapper_data_.
|
| + private_data_;
|
| + data.natives_cache_.Iterate(v);
|
| v->Synchronize("NativesCache");
|
| - extensions_cache.Iterate(v);
|
| + data.extensions_cache_.Iterate(v);
|
| v->Synchronize("Extensions");
|
| PendingFixups::Iterate(v);
|
| v->Synchronize("PendingFixups");
|
| @@ -400,8 +437,9 @@
|
|
|
|
|
| Genesis::~Genesis() {
|
| - ASSERT(current_ == this);
|
| - current_ = previous_;
|
| + Genesis* & current = v8_context()->bootstrapper_data_.private_data_.current_;
|
| + ASSERT(current == this);
|
| + current = previous_;
|
| }
|
|
|
|
|
| @@ -893,8 +931,8 @@
|
| #ifdef ENABLE_DEBUGGER_SUPPORT
|
| Debugger::set_compiling_natives(true);
|
| #endif
|
| - bool result =
|
| - CompileScriptCached(name, source, &natives_cache, NULL, true);
|
| + bool result = CompileScriptCached(name, source,
|
| + &v8_context()->bootstrapper_data_.private_data_.natives_cache_, NULL, true);
|
| ASSERT(Top::has_pending_exception() != result);
|
| if (!result) Top::clear_pending_exception();
|
| #ifdef ENABLE_DEBUGGER_SUPPORT
|
| @@ -1270,7 +1308,10 @@
|
| }
|
|
|
|
|
| +static MutexLockAdapter genesis_lock_adapter(OS::CreateMutex());
|
| +
|
| bool Genesis::InstallExtensions(v8::ExtensionConfiguration* extensions) {
|
| + V8SharedStateLocker locker(&genesis_lock_adapter);
|
| // Clear coloring of extension list
|
| v8::RegisteredExtension* current = v8::RegisteredExtension::first_extension();
|
| while (current != NULL) {
|
| @@ -1339,10 +1380,12 @@
|
| }
|
| 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);
|
| + bool result = CompileScriptCached(
|
| + CStrVector(extension->name()),
|
| + source_code,
|
| + &v8_context()->bootstrapper_data_.private_data_.extensions_cache_,
|
| + extension,
|
| + false);
|
| ASSERT(Top::has_pending_exception() != result);
|
| if (!result) {
|
| Top::clear_pending_exception();
|
| @@ -1575,8 +1618,9 @@
|
| // Link this genesis object into the stacked genesis chain. This
|
| // must be done before any early exits because the destructor
|
| // will always do unlinking.
|
| - previous_ = current_;
|
| - current_ = this;
|
| + Genesis* & current = v8_context()->bootstrapper_data_.private_data_.current_;
|
| + previous_ = current;
|
| + current = this;
|
| result_ = Handle<Context>::null();
|
|
|
| // If V8 isn't running and cannot be initialized, just return.
|
| @@ -1632,22 +1676,24 @@
|
|
|
| // Reserve space for statics needing saving and restoring.
|
| int Genesis::ArchiveSpacePerThread() {
|
| - return sizeof(current_);
|
| + return sizeof(v8_context()->bootstrapper_data_.private_data_.current_);
|
| }
|
|
|
|
|
| // Archive statics that are thread local.
|
| char* Genesis::ArchiveState(char* to) {
|
| - *reinterpret_cast<Genesis**>(to) = current_;
|
| - current_ = NULL;
|
| - return to + sizeof(current_);
|
| + Genesis* & current = v8_context()->bootstrapper_data_.private_data_.current_;
|
| + *reinterpret_cast<Genesis**>(to) = current;
|
| + current = NULL;
|
| + return to + sizeof(current);
|
| }
|
|
|
|
|
| // Restore statics that are thread local.
|
| char* Genesis::RestoreState(char* from) {
|
| - current_ = *reinterpret_cast<Genesis**>(from);
|
| - return from + sizeof(current_);
|
| + Genesis* & current = v8_context()->bootstrapper_data_.private_data_.current_;
|
| + current = *reinterpret_cast<Genesis**>(from);
|
| + return from + sizeof(current);
|
| }
|
|
|
| } } // namespace v8::internal
|
|
|