isolate.cc中定义的
struct StaticInitializer {
StaticInitializer() {
Isolate::EnsureDefaultIsolate();
}
} static_initializer;
StaticInitializer() {
Isolate::EnsureDefaultIsolate();
}
} static_initializer;
这个变量是一个Global变量,在C++初始化,早于main函数被调用之前就被调用了。
Isolate::EnsureDefaultIsolate()主要初始化Isolate中与Thread相关的一些静态变量
// defined at isolate.h
static Thread::LocalStorageKey per_isolate_thread_data_key_;
static Thread::LocalStorageKey isolate_key_;
static Thread::LocalStorageKey thread_id_key_;
static Isolate* default_isolate_;
static ThreadDataTable* thread_data_table_;
static Thread::LocalStorageKey isolate_key_;
static Thread::LocalStorageKey thread_id_key_;
static Isolate* default_isolate_;
static ThreadDataTable* thread_data_table_;
static inline bool EnsureInitializedForIsolate(i::Isolate* isolate,const char* location)
确保Isolate进行了初始化,如果没有,那么会调用InitializeHelper进行初始化,该函数会调用
bool V8::Initialize(Deserializer* des) {
InitializeOncePerProcess();//1
// The current thread may not yet had entered an isolate to run.
// Note the Isolate::Current() may be non-null because for various
// initialization purposes an initializing thread may be assigned an isolate
// but not actually enter it.
if (i::Isolate::CurrentPerIsolateThreadData() == NULL) {
i::Isolate::EnterDefaultIsolate();//2
}
InitializeOncePerProcess();//1
// The current thread may not yet had entered an isolate to run.
// Note the Isolate::Current() may be non-null because for various
// initialization purposes an initializing thread may be assigned an isolate
// but not actually enter it.
if (i::Isolate::CurrentPerIsolateThreadData() == NULL) {
i::Isolate::EnterDefaultIsolate();//2
}
。。。
return isolate->Init(des);//3
}
该函数主要有三点可说:
1.InitializeOncePerProcess
3.isolate->Init(des)
InitializeOncePerProcess最终会调用
void V8::InitializeOncePerProcessImpl() {
FlagList::EnforceFlagImplications();
if (FLAG_stress_compaction) {
FLAG_force_marking_deque_overflows = true;
FLAG_gc_global = true;
FLAG_max_new_space_size = (1 << (kPageSizeBits - 10)) * 2;
}
if (FLAG_trace_hydrogen) FLAG_parallel_recompilation = false;
OS::SetUp();
CPU::SetUp();
use_crankshaft_ = FLAG_crankshaft
&& !Serializer::enabled()
&& CPU::SupportsCrankshaft();
OS::PostSetUp();
RuntimeProfiler::GlobalSetUp();
ElementsAccessor::InitializeOncePerProcess();
LOperand::SetUpCaches();
SetUpJSCallerSavedCodeData();
SamplerRegistry::SetUp();
ExternalReference::SetUp();
}
FlagList::EnforceFlagImplications();
if (FLAG_stress_compaction) {
FLAG_force_marking_deque_overflows = true;
FLAG_gc_global = true;
FLAG_max_new_space_size = (1 << (kPageSizeBits - 10)) * 2;
}
if (FLAG_trace_hydrogen) FLAG_parallel_recompilation = false;
OS::SetUp();
CPU::SetUp();
use_crankshaft_ = FLAG_crankshaft
&& !Serializer::enabled()
&& CPU::SupportsCrankshaft();
OS::PostSetUp();
RuntimeProfiler::GlobalSetUp();
ElementsAccessor::InitializeOncePerProcess();
LOperand::SetUpCaches();
SetUpJSCallerSavedCodeData();
SamplerRegistry::SetUp();
ExternalReference::SetUp();
}
其中
CPU::SetUp函数会探测当前CPU的一些feature
// The Probe method needs executable memory, so it uses Heap::CreateCode.
// Allocation failure is silent and leads to safe default.
void CpuFeatures::Probe() {
ASSERT(!initialized_);
ASSERT(supported_ == 0);
#ifdef DEBUG
initialized_ = true;
#endif
if (Serializer::enabled()) {
supported_ |= OS::CpuFeaturesImpliedByPlatform();
return; // No features if we might serialize.
}
const int kBufferSize = 4 * KB;
VirtualMemory* memory = new VirtualMemory(kBufferSize);
if (!memory->IsReserved()) {
delete memory;
return;
}
ASSERT(memory->size() >= static_cast<size_t>(kBufferSize));
if (!memory->Commit(memory->address(), kBufferSize, true/*executable*/)) {
delete memory;
return;
}
Assembler assm(NULL, memory->address(), kBufferSize);
Label cpuid, done;
#define __ assm.
// Save old esp, since we are going to modify the stack.
__ push(ebp);
__ pushfd();
__ push(ecx);
__ push(ebx);
__ mov(ebp, esp);
// If we can modify bit 21 of the EFLAGS register, then CPUID is supported.
__ pushfd(); //把EFLAGS寄存器入栈
__ pop(eax);
__ mov(edx, eax);
__ xor_(eax, 0x200000); // Flip bit 21.
__ push(eax);
__ popfd();
__ pushfd();
__ pop(eax);
// Allocation failure is silent and leads to safe default.
void CpuFeatures::Probe() {
ASSERT(!initialized_);
ASSERT(supported_ == 0);
#ifdef DEBUG
initialized_ = true;
#endif
if (Serializer::enabled()) {
supported_ |= OS::CpuFeaturesImpliedByPlatform();
return; // No features if we might serialize.
}
const int kBufferSize = 4 * KB;
VirtualMemory* memory = new VirtualMemory(kBufferSize);
if (!memory->IsReserved()) {
delete memory;
return;
}
ASSERT(memory->size() >= static_cast<size_t>(kBufferSize));
if (!memory->Commit(memory->address(), kBufferSize, true/*executable*/)) {
delete memory;
return;
}
Assembler assm(NULL, memory->address(), kBufferSize);
Label cpuid, done;
#define __ assm.
// Save old esp, since we are going to modify the stack.
__ push(ebp);
__ pushfd();
__ push(ecx);
__ push(ebx);
__ mov(ebp, esp);
// If we can modify bit 21 of the EFLAGS register, then CPUID is supported.
__ pushfd(); //把EFLAGS寄存器入栈
__ pop(eax);
__ mov(edx, eax);
__ xor_(eax, 0x200000); // Flip bit 21.
__ push(eax);
__ popfd();
__ pushfd();
__ pop(eax);
//此时eax为修改后的EFLAGS,edx为修改前的EFLAGS
__ xor_(eax, edx); // Different if CPUID is supported.
__ j(not_zero, &cpuid);
// CPUID not supported. Clear the supported features in edx:eax.
__ xor_(eax, eax);
__ xor_(edx, edx);
__ jmp(&done);
// Invoke CPUID with 1 in eax to get feature information in
// ecx:edx. Temporarily enable CPUID support because we know it's
// safe here.
__ bind(&cpuid);
__ mov(eax, 1);
supported_ = (1 << CPUID);
{ CpuFeatureScope fscope(&assm, CPUID);
__ cpuid();
}
supported_ = 0;
// Move the result from ecx:edx to edx:eax and make sure to mark the
// CPUID feature as supported.
__ mov(eax, edx);
__ or_(eax, 1 << CPUID);
__ mov(edx, ecx);
// Done.
__ bind(&done);
__ mov(esp, ebp);
__ pop(ebx);
__ pop(ecx);
__ popfd();
__ pop(ebp);
__ ret(0);
#undef __
typedef uint64_t (*F0)();
F0 probe = FUNCTION_CAST<F0>(reinterpret_cast<Address>(memory->address()));
uint64_t probed_features = probe(); //5.把返回地址强转为函数指针,执行之。
uint64_t platform_features = OS::CpuFeaturesImpliedByPlatform();
supported_ = probed_features | platform_features;
found_by_runtime_probing_only_ = probed_featur
__ xor_(eax, edx); // Different if CPUID is supported.
__ j(not_zero, &cpuid);
// CPUID not supported. Clear the supported features in edx:eax.
__ xor_(eax, eax);
__ xor_(edx, edx);
__ jmp(&done);
// Invoke CPUID with 1 in eax to get feature information in
// ecx:edx. Temporarily enable CPUID support because we know it's
// safe here.
__ bind(&cpuid);
__ mov(eax, 1);
supported_ = (1 << CPUID);
{ CpuFeatureScope fscope(&assm, CPUID);
__ cpuid();
}
supported_ = 0;
// Move the result from ecx:edx to edx:eax and make sure to mark the
// CPUID feature as supported.
__ mov(eax, edx);
__ or_(eax, 1 << CPUID);
__ mov(edx, ecx);
// Done.
__ bind(&done);
__ mov(esp, ebp);
__ pop(ebx);
__ pop(ecx);
__ popfd();
__ pop(ebp);
__ ret(0);
#undef __
typedef uint64_t (*F0)();
F0 probe = FUNCTION_CAST<F0>(reinterpret_cast<Address>(memory->address()));
uint64_t probed_features = probe(); //5.把返回地址强转为函数指针,执行之。
uint64_t platform_features = OS::CpuFeaturesImpliedByPlatform();
supported_ = probed_features | platform_features;
found_by_runtime_probing_only_ = probed_featur