StaticInitializer() {
Isolate::EnsureDefaultIsolate();
}
} static_initializer;
static Thread::LocalStorageKey isolate_key_;
static Thread::LocalStorageKey thread_id_key_;
static Isolate* default_isolate_;
static ThreadDataTable* thread_data_table_;
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
}
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();
}
// 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);
__ 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_features & ~platform_features;
delete memory;
}
// Math functions depend on CPU features therefore they are initialized after
// CPU.
MathSetup();
#if defined(V8_TARGET_ARCH_IA32)
memcopy_function = CreateMemCopyFunction();
#endif
}
Register loop_count = ecx;
Register count = edx;
__ shr(loop_count, 5);//除以32,因爲每次都會複製32字節
{
// Main copy loop.
Label loop;
__ bind(&loop);
__ prefetch(Operand(src, 0x20), 1);//預取src後32字節的數據,因爲每次都是複製32字節
__ movdqa(xmm0, Operand(src, 0x00));//複製src地址開始的16字節到xmm0寄存器
__ movdqa(xmm1, Operand(src, 0x10));//複製src+16地址開始的16字節到xmm0寄存器
__ add(src, Immediate(0x20));
__ movdqa(Operand(dst, 0x00), xmm0);//複製mm0寄存器內容到dst地址
__ movdqa(Operand(dst, 0x10), xmm1);//複製mm1寄存器內容到dst+16地址
__ add(dst, Immediate(0x20));
__ dec(loop_count);
__ j(not_zero, &loop);
}
// entered. That instance is allocated when the isolate is initially entered
// and reused on subsequent entries.
Isolate* current_isolate = NULL;
PerIsolateThreadData* current_data = CurrentPerIsolateThreadData();
if (current_data != NULL) {
current_isolate = current_data->isolate_;
ASSERT(current_isolate != NULL);
if (current_isolate == this) {
ASSERT(Current() == this);
ASSERT(entry_stack_ != NULL);
ASSERT(entry_stack_->previous_thread_data == NULL ||
entry_stack_->previous_thread_data->thread_id().Equals(
ThreadId::Current()));
// Same thread re-enters the isolate, no need to re-init anything.
entry_stack_->entry_count++;
return;
}
}
// Threads can have default isolate set into TLS as Current but not yet have
// PerIsolateThreadData for it, as it requires more advanced phase of the
// initialization. For example, a thread might be the one that system used for
// static initializers - in this case the default isolate is set in TLS but
// the thread did not yet Enter the isolate. If PerisolateThreadData is not
// there, use the isolate set in TLS.
if (current_isolate == NULL) {
current_isolate = Isolate::UncheckedCurrent();
}
PerIsolateThreadData* data = FindOrAllocatePerThreadDataForThisThread();
ASSERT(data != NULL);
ASSERT(data->isolate_ == this);
EntryStackItem* item = new EntryStackItem(current_data,
current_isolate,
entry_stack_);
entry_stack_ = item;
SetIsolateThreadLocals(this, data);
// In case it's the first time some thread enters the isolate.
set_thread_id(data->thread_id());
}
// the Isolate. The top of the stack points to a thread which is currently
// running the Isolate. When the stack is empty, the Isolate is considered
// not entered by any thread and can be Disposed.
// If the same thread enters the Isolate more then once, the entry_count_
// is incremented rather then a new item pushed to the stack.
class EntryStackItem定義於isolate.h
bool should_set_stack_limits = false;
if (real_climit_ == kIllegalLimit) {
// Takes the address of the limit variable in order to find out where
// the top of stack is right now.
const uintptr_t kLimitSize = FLAG_stack_size * KB;
uintptr_t limit = reinterpret_cast<uintptr_t>(&limit) - kLimitSize;//使用臨時變量limit的地址作爲棧基地址,計算stack limit,在模擬器上使用的stack size是492kB
ASSERT(reinterpret_cast<uintptr_t>(&limit) > kLimitSize);
real_jslimit_ = SimulatorStack::JsLimitFromCLimit(isolate, limit);
jslimit_ = SimulatorStack::JsLimitFromCLimit(isolate, limit);
real_climit_ = limit;
climit_ = limit;
should_set_stack_limits = true;
}
nesting_ = 0;
postpone_interrupts_nesting_ = 0;
interrupt_flags_ = 0;
return should_set_stack_li
}
First -------------- next ------------------------>| --+-------->| |-------------- ---------------| |------|------| Extention\/----------------------------| name |----------------------------| source |----------------------------| GetNativeFunction |----------------------------/_\|----------------------------| GCExtention |----------------------------