Version 3.17.13
Turned Flags into a uint32_t typedef (Chromium issue 194749).
Performance and stability improvements on all platforms.
git-svn-id: http://v8.googlecode.com/svn/trunk@13993 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
diff --git a/src/api.cc b/src/api.cc
index 64c0022..dfa5765 100644
--- a/src/api.cc
+++ b/src/api.cc
@@ -6454,6 +6454,11 @@
}
+unsigned CpuProfileNode::GetNodeId() const {
+ return reinterpret_cast<const i::ProfileNode*>(this)->id();
+}
+
+
int CpuProfileNode::GetChildrenCount() const {
i::Isolate* isolate = i::Isolate::Current();
IsDeadCheck(isolate, "v8::CpuProfileNode::GetChildrenCount");
@@ -6473,11 +6478,12 @@
void CpuProfile::Delete() {
i::Isolate* isolate = i::Isolate::Current();
IsDeadCheck(isolate, "v8::CpuProfile::Delete");
- i::CpuProfiler::DeleteProfile(reinterpret_cast<i::CpuProfile*>(this));
- if (i::CpuProfiler::GetProfilesCount() == 0 &&
- !i::CpuProfiler::HasDetachedProfiles()) {
+ i::CpuProfiler* profiler = isolate->cpu_profiler();
+ ASSERT(profiler != NULL);
+ profiler->DeleteProfile(reinterpret_cast<i::CpuProfile*>(this));
+ if (profiler->GetProfilesCount() == 0 && !profiler->HasDetachedProfiles()) {
// If this was the last profile, clean up all accessory data as well.
- i::CpuProfiler::DeleteAllProfiles();
+ profiler->DeleteAllProfiles();
}
}
@@ -6506,10 +6512,23 @@
}
+const CpuProfileNode* CpuProfile::GetSample(int index) const {
+ const i::CpuProfile* profile = reinterpret_cast<const i::CpuProfile*>(this);
+ return reinterpret_cast<const CpuProfileNode*>(profile->sample(index));
+}
+
+
+int CpuProfile::GetSamplesCount() const {
+ return reinterpret_cast<const i::CpuProfile*>(this)->samples_count();
+}
+
+
int CpuProfiler::GetProfilesCount() {
i::Isolate* isolate = i::Isolate::Current();
IsDeadCheck(isolate, "v8::CpuProfiler::GetProfilesCount");
- return i::CpuProfiler::GetProfilesCount();
+ i::CpuProfiler* profiler = isolate->cpu_profiler();
+ ASSERT(profiler != NULL);
+ return profiler->GetProfilesCount();
}
@@ -6517,8 +6536,10 @@
Handle<Value> security_token) {
i::Isolate* isolate = i::Isolate::Current();
IsDeadCheck(isolate, "v8::CpuProfiler::GetProfile");
+ i::CpuProfiler* profiler = isolate->cpu_profiler();
+ ASSERT(profiler != NULL);
return reinterpret_cast<const CpuProfile*>(
- i::CpuProfiler::GetProfile(
+ profiler->GetProfile(
security_token.IsEmpty() ? NULL : *Utils::OpenHandle(*security_token),
index));
}
@@ -6528,17 +6549,21 @@
Handle<Value> security_token) {
i::Isolate* isolate = i::Isolate::Current();
IsDeadCheck(isolate, "v8::CpuProfiler::FindProfile");
+ i::CpuProfiler* profiler = isolate->cpu_profiler();
+ ASSERT(profiler != NULL);
return reinterpret_cast<const CpuProfile*>(
- i::CpuProfiler::FindProfile(
+ profiler->FindProfile(
security_token.IsEmpty() ? NULL : *Utils::OpenHandle(*security_token),
uid));
}
-void CpuProfiler::StartProfiling(Handle<String> title) {
+void CpuProfiler::StartProfiling(Handle<String> title, bool record_samples) {
i::Isolate* isolate = i::Isolate::Current();
IsDeadCheck(isolate, "v8::CpuProfiler::StartProfiling");
- i::CpuProfiler::StartProfiling(*Utils::OpenHandle(*title));
+ i::CpuProfiler* profiler = isolate->cpu_profiler();
+ ASSERT(profiler != NULL);
+ profiler->StartProfiling(*Utils::OpenHandle(*title), record_samples);
}
@@ -6546,8 +6571,10 @@
Handle<Value> security_token) {
i::Isolate* isolate = i::Isolate::Current();
IsDeadCheck(isolate, "v8::CpuProfiler::StopProfiling");
+ i::CpuProfiler* profiler = isolate->cpu_profiler();
+ ASSERT(profiler != NULL);
return reinterpret_cast<const CpuProfile*>(
- i::CpuProfiler::StopProfiling(
+ profiler->StopProfiling(
security_token.IsEmpty() ? NULL : *Utils::OpenHandle(*security_token),
*Utils::OpenHandle(*title)));
}
@@ -6556,7 +6583,9 @@
void CpuProfiler::DeleteAllProfiles() {
i::Isolate* isolate = i::Isolate::Current();
IsDeadCheck(isolate, "v8::CpuProfiler::DeleteAllProfiles");
- i::CpuProfiler::DeleteAllProfiles();
+ i::CpuProfiler* profiler = isolate->cpu_profiler();
+ ASSERT(profiler != NULL);
+ profiler->DeleteAllProfiles();
}
diff --git a/src/bootstrapper.cc b/src/bootstrapper.cc
index 3ef8d37..58b2ad0 100644
--- a/src/bootstrapper.cc
+++ b/src/bootstrapper.cc
@@ -147,23 +147,13 @@
v8::ExtensionConfiguration* extensions);
~Genesis() { }
- Handle<Context> result() { return result_; }
-
- Genesis* previous() { return previous_; }
-
Isolate* isolate() const { return isolate_; }
Factory* factory() const { return isolate_->factory(); }
Heap* heap() const { return isolate_->heap(); }
+ Handle<Context> result() { return result_; }
+
private:
- Handle<Context> native_context_;
- Isolate* isolate_;
-
- // There may be more than one active genesis object: When GC is
- // triggered during environment creation there may be weak handle
- // processing callbacks which may create new environments.
- Genesis* previous_;
-
Handle<Context> native_context() { return native_context_; }
// Creates some basic objects. Used for creating a context from scratch.
@@ -284,7 +274,9 @@
Handle<Context> top_context,
bool use_runtime_context);
+ Isolate* isolate_;
Handle<Context> result_;
+ Handle<Context> native_context_;
// Function instance maps. Function literal maps are created initially with
// a read only prototype for the processing of JS builtins. Later the function
@@ -310,9 +302,9 @@
v8::Handle<v8::ObjectTemplate> global_template,
v8::ExtensionConfiguration* extensions) {
HandleScope scope(isolate_);
- Handle<Context> env;
Genesis genesis(isolate_, global_object, global_template, extensions);
- env = genesis.result();
+ Handle<Object> context(isolate_->global_handles()->Create(*genesis.result()));
+ Handle<Context> env = Handle<Context>::cast(context);
if (!env.is_null()) {
if (InstallExtensions(env, extensions)) {
return env;
@@ -699,9 +691,8 @@
// closure and extension object later (we need the empty function
// and the global object, but in order to create those, we need the
// native context).
- native_context_ = Handle<Context>::cast(isolate()->global_handles()->Create(
- *factory()->NewNativeContext()));
- AddToWeakNativeContextList(*native_context_);
+ native_context_ = factory()->NewNativeContext();
+ AddToWeakNativeContextList(*native_context());
isolate()->set_context(*native_context());
// Allocate the message listeners object.
@@ -830,11 +821,11 @@
void Genesis::HookUpInnerGlobal(Handle<GlobalObject> inner_global) {
Handle<GlobalObject> inner_global_from_snapshot(
- GlobalObject::cast(native_context_->extension()));
- Handle<JSBuiltinsObject> builtins_global(native_context_->builtins());
- native_context_->set_extension(*inner_global);
- native_context_->set_global_object(*inner_global);
- native_context_->set_security_token(*inner_global);
+ GlobalObject::cast(native_context()->extension()));
+ Handle<JSBuiltinsObject> builtins_global(native_context()->builtins());
+ native_context()->set_extension(*inner_global);
+ native_context()->set_global_object(*inner_global);
+ native_context()->set_security_token(*inner_global);
static const PropertyAttributes attributes =
static_cast<PropertyAttributes>(READ_ONLY | DONT_DELETE);
ForceSetProperty(builtins_global,
@@ -2424,7 +2415,6 @@
// Before creating the roots we must save the context and restore it
// on all function exits.
- HandleScope scope(isolate);
SaveContext saved_context(isolate);
// During genesis, the boilerplate for stack overflow won't work until the
@@ -2433,12 +2423,10 @@
StackLimitCheck check(isolate);
if (check.HasOverflowed()) return;
- Handle<Context> new_context = Snapshot::NewContextFromSnapshot();
- if (!new_context.is_null()) {
- native_context_ =
- Handle<Context>::cast(isolate->global_handles()->Create(*new_context));
- AddToWeakNativeContextList(*native_context_);
- isolate->set_context(*native_context_);
+ native_context_ = Snapshot::NewContextFromSnapshot();
+ if (!native_context().is_null()) {
+ AddToWeakNativeContextList(*native_context());
+ isolate->set_context(*native_context());
isolate->counters()->contexts_created_by_snapshot()->Increment();
Handle<GlobalObject> inner_global;
Handle<JSGlobalProxy> global_proxy =
@@ -2474,7 +2462,7 @@
InitializeExperimentalGlobal();
if (!InstallExperimentalNatives()) return;
- result_ = native_context_;
+ result_ = native_context();
}
diff --git a/src/codegen.cc b/src/codegen.cc
index 508e221..90ab2b5 100644
--- a/src/codegen.cc
+++ b/src/codegen.cc
@@ -171,7 +171,8 @@
bool CodeGenerator::ShouldGenerateLog(Expression* type) {
ASSERT(type != NULL);
Isolate* isolate = Isolate::Current();
- if (!isolate->logger()->is_logging() && !CpuProfiler::is_profiling(isolate)) {
+ if (!isolate->logger()->is_logging() &&
+ !isolate->cpu_profiler()->is_profiling()) {
return false;
}
Handle<String> name = Handle<String>::cast(type->AsLiteral()->handle());
diff --git a/src/compiler.cc b/src/compiler.cc
index 21ea25f..2c4dae5 100644
--- a/src/compiler.cc
+++ b/src/compiler.cc
@@ -1134,7 +1134,7 @@
// script name and line number. Check explicitly whether logging is
// enabled as finding the line number is not free.
if (info->isolate()->logger()->is_logging_code_events() ||
- CpuProfiler::is_profiling(info->isolate())) {
+ info->isolate()->cpu_profiler()->is_profiling()) {
Handle<Script> script = info->script();
Handle<Code> code = info->code();
if (*code == info->isolate()->builtins()->builtin(Builtins::kLazyCompile))
diff --git a/src/cpu-profiler.cc b/src/cpu-profiler.cc
index 15edc1e..7979eb4 100644
--- a/src/cpu-profiler.cc
+++ b/src/cpu-profiler.cc
@@ -258,109 +258,66 @@
}
-void CpuProfiler::StartProfiling(const char* title) {
- ASSERT(Isolate::Current()->cpu_profiler() != NULL);
- Isolate::Current()->cpu_profiler()->StartCollectingProfile(title);
-}
-
-
-void CpuProfiler::StartProfiling(String* title) {
- ASSERT(Isolate::Current()->cpu_profiler() != NULL);
- Isolate::Current()->cpu_profiler()->StartCollectingProfile(title);
-}
-
-
-CpuProfile* CpuProfiler::StopProfiling(const char* title) {
- Isolate* isolate = Isolate::Current();
- return is_profiling(isolate) ?
- isolate->cpu_profiler()->StopCollectingProfile(title) : NULL;
-}
-
-
-CpuProfile* CpuProfiler::StopProfiling(Object* security_token, String* title) {
- Isolate* isolate = Isolate::Current();
- return is_profiling(isolate) ?
- isolate->cpu_profiler()->StopCollectingProfile(
- security_token, title) : NULL;
-}
-
-
int CpuProfiler::GetProfilesCount() {
- ASSERT(Isolate::Current()->cpu_profiler() != NULL);
// The count of profiles doesn't depend on a security token.
- return Isolate::Current()->cpu_profiler()->profiles_->Profiles(
- TokenEnumerator::kNoSecurityToken)->length();
+ return profiles_->Profiles(TokenEnumerator::kNoSecurityToken)->length();
}
CpuProfile* CpuProfiler::GetProfile(Object* security_token, int index) {
- ASSERT(Isolate::Current()->cpu_profiler() != NULL);
- CpuProfiler* profiler = Isolate::Current()->cpu_profiler();
- const int token = profiler->token_enumerator_->GetTokenId(security_token);
- return profiler->profiles_->Profiles(token)->at(index);
+ const int token = token_enumerator_->GetTokenId(security_token);
+ return profiles_->Profiles(token)->at(index);
}
CpuProfile* CpuProfiler::FindProfile(Object* security_token, unsigned uid) {
- ASSERT(Isolate::Current()->cpu_profiler() != NULL);
- CpuProfiler* profiler = Isolate::Current()->cpu_profiler();
- const int token = profiler->token_enumerator_->GetTokenId(security_token);
- return profiler->profiles_->GetProfile(token, uid);
+ const int token = token_enumerator_->GetTokenId(security_token);
+ return profiles_->GetProfile(token, uid);
}
-TickSample* CpuProfiler::TickSampleEvent(Isolate* isolate) {
- if (CpuProfiler::is_profiling(isolate)) {
- return isolate->cpu_profiler()->processor_->TickSampleEvent();
- } else {
- return NULL;
- }
+TickSample* CpuProfiler::TickSampleEvent() {
+ if (is_profiling_) return processor_->TickSampleEvent();
+ return NULL;
}
void CpuProfiler::DeleteAllProfiles() {
- Isolate* isolate = Isolate::Current();
- ASSERT(isolate->cpu_profiler() != NULL);
- if (is_profiling(isolate)) {
- isolate->cpu_profiler()->StopProcessor();
- }
- isolate->cpu_profiler()->ResetProfiles();
+ if (is_profiling_) StopProcessor();
+ ResetProfiles();
}
void CpuProfiler::DeleteProfile(CpuProfile* profile) {
- ASSERT(Isolate::Current()->cpu_profiler() != NULL);
- Isolate::Current()->cpu_profiler()->profiles_->RemoveProfile(profile);
+ profiles_->RemoveProfile(profile);
delete profile;
}
bool CpuProfiler::HasDetachedProfiles() {
- ASSERT(Isolate::Current()->cpu_profiler() != NULL);
- return Isolate::Current()->cpu_profiler()->profiles_->HasDetachedProfiles();
+ return profiles_->HasDetachedProfiles();
}
void CpuProfiler::CallbackEvent(Name* name, Address entry_point) {
- Isolate::Current()->cpu_profiler()->processor_->CallbackCreateEvent(
+ processor_->CallbackCreateEvent(
Logger::CALLBACK_TAG, CodeEntry::kEmptyNamePrefix, name, entry_point);
}
void CpuProfiler::CodeCreateEvent(Logger::LogEventsAndTags tag,
Code* code, const char* comment) {
- Isolate::Current()->cpu_profiler()->processor_->CodeCreateEvent(
+ processor_->CodeCreateEvent(
tag, comment, code->address(), code->ExecutableSize());
}
void CpuProfiler::CodeCreateEvent(Logger::LogEventsAndTags tag,
Code* code, Name* name) {
- Isolate* isolate = Isolate::Current();
- isolate->cpu_profiler()->processor_->CodeCreateEvent(
+ processor_->CodeCreateEvent(
tag,
name,
- isolate->heap()->empty_string(),
+ isolate_->heap()->empty_string(),
v8::CpuProfileNode::kNoLineNumberInfo,
code->address(),
code->ExecutableSize(),
@@ -372,11 +329,10 @@
Code* code,
SharedFunctionInfo* shared,
Name* name) {
- Isolate* isolate = Isolate::Current();
- isolate->cpu_profiler()->processor_->CodeCreateEvent(
+ processor_->CodeCreateEvent(
tag,
name,
- isolate->heap()->empty_string(),
+ isolate_->heap()->empty_string(),
v8::CpuProfileNode::kNoLineNumberInfo,
code->address(),
code->ExecutableSize(),
@@ -388,7 +344,7 @@
Code* code,
SharedFunctionInfo* shared,
String* source, int line) {
- Isolate::Current()->cpu_profiler()->processor_->CodeCreateEvent(
+ processor_->CodeCreateEvent(
tag,
shared->DebugName(),
source,
@@ -401,7 +357,7 @@
void CpuProfiler::CodeCreateEvent(Logger::LogEventsAndTags tag,
Code* code, int args_count) {
- Isolate::Current()->cpu_profiler()->processor_->CodeCreateEvent(
+ processor_->CodeCreateEvent(
tag,
args_count,
code->address(),
@@ -410,7 +366,7 @@
void CpuProfiler::CodeMoveEvent(Address from, Address to) {
- Isolate::Current()->cpu_profiler()->processor_->CodeMoveEvent(from, to);
+ processor_->CodeMoveEvent(from, to);
}
@@ -419,19 +375,18 @@
void CpuProfiler::SharedFunctionInfoMoveEvent(Address from, Address to) {
- CpuProfiler* profiler = Isolate::Current()->cpu_profiler();
- profiler->processor_->SharedFunctionInfoMoveEvent(from, to);
+ processor_->SharedFunctionInfoMoveEvent(from, to);
}
void CpuProfiler::GetterCallbackEvent(Name* name, Address entry_point) {
- Isolate::Current()->cpu_profiler()->processor_->CallbackCreateEvent(
+ processor_->CallbackCreateEvent(
Logger::CALLBACK_TAG, "get ", name, entry_point);
}
void CpuProfiler::RegExpCodeCreateEvent(Code* code, String* source) {
- Isolate::Current()->cpu_profiler()->processor_->RegExpCodeCreateEvent(
+ processor_->RegExpCodeCreateEvent(
Logger::REG_EXP_TAG,
"RegExp: ",
source,
@@ -441,13 +396,14 @@
void CpuProfiler::SetterCallbackEvent(Name* name, Address entry_point) {
- Isolate::Current()->cpu_profiler()->processor_->CallbackCreateEvent(
+ processor_->CallbackCreateEvent(
Logger::CALLBACK_TAG, "set ", name, entry_point);
}
-CpuProfiler::CpuProfiler()
- : profiles_(new CpuProfilesCollection()),
+CpuProfiler::CpuProfiler(Isolate* isolate)
+ : isolate_(isolate),
+ profiles_(new CpuProfilesCollection()),
next_profile_uid_(1),
token_enumerator_(new TokenEnumerator()),
generator_(NULL),
@@ -468,43 +424,41 @@
profiles_ = new CpuProfilesCollection();
}
-void CpuProfiler::StartCollectingProfile(const char* title) {
- if (profiles_->StartProfiling(title, next_profile_uid_++)) {
+void CpuProfiler::StartProfiling(const char* title, bool record_samples) {
+ if (profiles_->StartProfiling(title, next_profile_uid_++, record_samples)) {
StartProcessorIfNotStarted();
}
processor_->AddCurrentStack();
}
-void CpuProfiler::StartCollectingProfile(String* title) {
- StartCollectingProfile(profiles_->GetName(title));
+void CpuProfiler::StartProfiling(String* title, bool record_samples) {
+ StartProfiling(profiles_->GetName(title), record_samples);
}
void CpuProfiler::StartProcessorIfNotStarted() {
if (processor_ == NULL) {
- Isolate* isolate = Isolate::Current();
-
// Disable logging when using the new implementation.
- saved_logging_nesting_ = isolate->logger()->logging_nesting_;
- isolate->logger()->logging_nesting_ = 0;
+ saved_logging_nesting_ = isolate_->logger()->logging_nesting_;
+ isolate_->logger()->logging_nesting_ = 0;
generator_ = new ProfileGenerator(profiles_);
processor_ = new ProfilerEventsProcessor(generator_);
is_profiling_ = true;
processor_->Start();
// Enumerate stuff we already have in the heap.
- if (isolate->heap()->HasBeenSetUp()) {
+ if (isolate_->heap()->HasBeenSetUp()) {
if (!FLAG_prof_browser_mode) {
bool saved_log_code_flag = FLAG_log_code;
FLAG_log_code = true;
- isolate->logger()->LogCodeObjects();
+ isolate_->logger()->LogCodeObjects();
FLAG_log_code = saved_log_code_flag;
}
- isolate->logger()->LogCompiledFunctions();
- isolate->logger()->LogAccessorCallbacks();
+ isolate_->logger()->LogCompiledFunctions();
+ isolate_->logger()->LogAccessorCallbacks();
}
// Enable stack sampling.
- Sampler* sampler = reinterpret_cast<Sampler*>(isolate->logger()->ticker_);
+ Sampler* sampler = reinterpret_cast<Sampler*>(isolate_->logger()->ticker_);
if (!sampler->IsActive()) {
sampler->Start();
need_to_stop_sampler_ = true;
@@ -514,7 +468,8 @@
}
-CpuProfile* CpuProfiler::StopCollectingProfile(const char* title) {
+CpuProfile* CpuProfiler::StopProfiling(const char* title) {
+ if (!is_profiling_) return NULL;
const double actual_sampling_rate = generator_->actual_sampling_rate();
StopProcessorIfLastProfile(title);
CpuProfile* result =
@@ -528,8 +483,8 @@
}
-CpuProfile* CpuProfiler::StopCollectingProfile(Object* security_token,
- String* title) {
+CpuProfile* CpuProfiler::StopProfiling(Object* security_token, String* title) {
+ if (!is_profiling_) return NULL;
const double actual_sampling_rate = generator_->actual_sampling_rate();
const char* profile_title = profiles_->GetName(title);
StopProcessorIfLastProfile(profile_title);
@@ -544,7 +499,7 @@
void CpuProfiler::StopProcessor() {
- Logger* logger = Isolate::Current()->logger();
+ Logger* logger = isolate_->logger();
Sampler* sampler = reinterpret_cast<Sampler*>(logger->ticker_);
sampler->DecreaseProfilingDepth();
if (need_to_stop_sampler_) {
@@ -562,20 +517,4 @@
}
-void CpuProfiler::SetUp() {
- Isolate* isolate = Isolate::Current();
- if (isolate->cpu_profiler() == NULL) {
- isolate->set_cpu_profiler(new CpuProfiler());
- }
-}
-
-
-void CpuProfiler::TearDown() {
- Isolate* isolate = Isolate::Current();
- if (isolate->cpu_profiler() != NULL) {
- delete isolate->cpu_profiler();
- }
- isolate->set_cpu_profiler(NULL);
-}
-
} } // namespace v8::internal
diff --git a/src/cpu-profiler.h b/src/cpu-profiler.h
index 3dc766b..89d9c81 100644
--- a/src/cpu-profiler.h
+++ b/src/cpu-profiler.h
@@ -184,84 +184,71 @@
unsigned enqueue_order_;
};
-} } // namespace v8::internal
-
-#define PROFILE(isolate, Call) \
- LOG_CODE_EVENT(isolate, Call); \
- do { \
- if (v8::internal::CpuProfiler::is_profiling(isolate)) { \
- v8::internal::CpuProfiler::Call; \
- } \
+#define PROFILE(IsolateGetter, Call) \
+ do { \
+ Isolate* cpu_profiler_isolate = (IsolateGetter); \
+ LOG_CODE_EVENT(cpu_profiler_isolate, Call); \
+ CpuProfiler* cpu_profiler = cpu_profiler_isolate->cpu_profiler(); \
+ if (cpu_profiler->is_profiling()) { \
+ cpu_profiler->Call; \
+ } \
} while (false)
-namespace v8 {
-namespace internal {
-
-
-// TODO(isolates): isolatify this class.
class CpuProfiler {
public:
- static void SetUp();
- static void TearDown();
+ explicit CpuProfiler(Isolate* isolate);
+ ~CpuProfiler();
- static void StartProfiling(const char* title);
- static void StartProfiling(String* title);
- static CpuProfile* StopProfiling(const char* title);
- static CpuProfile* StopProfiling(Object* security_token, String* title);
- static int GetProfilesCount();
- static CpuProfile* GetProfile(Object* security_token, int index);
- static CpuProfile* FindProfile(Object* security_token, unsigned uid);
- static void DeleteAllProfiles();
- static void DeleteProfile(CpuProfile* profile);
- static bool HasDetachedProfiles();
+ void StartProfiling(const char* title, bool record_samples = false);
+ void StartProfiling(String* title, bool record_samples);
+ CpuProfile* StopProfiling(const char* title);
+ CpuProfile* StopProfiling(Object* security_token, String* title);
+ int GetProfilesCount();
+ CpuProfile* GetProfile(Object* security_token, int index);
+ CpuProfile* FindProfile(Object* security_token, unsigned uid);
+ void DeleteAllProfiles();
+ void DeleteProfile(CpuProfile* profile);
+ bool HasDetachedProfiles();
// Invoked from stack sampler (thread or signal handler.)
- static TickSample* TickSampleEvent(Isolate* isolate);
+ TickSample* TickSampleEvent();
// Must be called via PROFILE macro, otherwise will crash when
// profiling is not enabled.
- static void CallbackEvent(Name* name, Address entry_point);
- static void CodeCreateEvent(Logger::LogEventsAndTags tag,
- Code* code, const char* comment);
- static void CodeCreateEvent(Logger::LogEventsAndTags tag,
- Code* code, Name* name);
- static void CodeCreateEvent(Logger::LogEventsAndTags tag,
- Code* code,
+ void CallbackEvent(Name* name, Address entry_point);
+ void CodeCreateEvent(Logger::LogEventsAndTags tag,
+ Code* code, const char* comment);
+ void CodeCreateEvent(Logger::LogEventsAndTags tag,
+ Code* code, Name* name);
+ void CodeCreateEvent(Logger::LogEventsAndTags tag,
+ Code* code,
SharedFunctionInfo* shared,
Name* name);
- static void CodeCreateEvent(Logger::LogEventsAndTags tag,
- Code* code,
- SharedFunctionInfo* shared,
- String* source, int line);
- static void CodeCreateEvent(Logger::LogEventsAndTags tag,
- Code* code, int args_count);
- static void CodeMovingGCEvent() {}
- static void CodeMoveEvent(Address from, Address to);
- static void CodeDeleteEvent(Address from);
- static void GetterCallbackEvent(Name* name, Address entry_point);
- static void RegExpCodeCreateEvent(Code* code, String* source);
- static void SetterCallbackEvent(Name* name, Address entry_point);
- static void SharedFunctionInfoMoveEvent(Address from, Address to);
+ void CodeCreateEvent(Logger::LogEventsAndTags tag,
+ Code* code,
+ SharedFunctionInfo* shared,
+ String* source, int line);
+ void CodeCreateEvent(Logger::LogEventsAndTags tag,
+ Code* code, int args_count);
+ void CodeMovingGCEvent() {}
+ void CodeMoveEvent(Address from, Address to);
+ void CodeDeleteEvent(Address from);
+ void GetterCallbackEvent(Name* name, Address entry_point);
+ void RegExpCodeCreateEvent(Code* code, String* source);
+ void SetterCallbackEvent(Name* name, Address entry_point);
+ void SharedFunctionInfoMoveEvent(Address from, Address to);
- static INLINE(bool is_profiling(Isolate* isolate)) {
- CpuProfiler* profiler = isolate->cpu_profiler();
- return profiler != NULL && profiler->is_profiling_;
- }
+ INLINE(bool is_profiling() const) { return is_profiling_; }
private:
- CpuProfiler();
- ~CpuProfiler();
- void StartCollectingProfile(const char* title);
- void StartCollectingProfile(String* title);
void StartProcessorIfNotStarted();
- CpuProfile* StopCollectingProfile(const char* title);
- CpuProfile* StopCollectingProfile(Object* security_token, String* title);
void StopProcessorIfLastProfile(const char* title);
void StopProcessor();
void ResetProfiles();
+ Isolate* isolate_;
CpuProfilesCollection* profiles_;
unsigned next_profile_uid_;
TokenEnumerator* token_enumerator_;
diff --git a/src/d8.cc b/src/d8.cc
index 00b23fb..805a0cf 100644
--- a/src/d8.cc
+++ b/src/d8.cc
@@ -215,7 +215,9 @@
} else {
ASSERT(!try_catch.HasCaught());
if (print_result) {
+#if !defined(V8_SHARED)
if (options.test_shell) {
+#endif
if (!result->IsUndefined()) {
// If all went well and the result wasn't undefined then print
// the returned value.
@@ -223,6 +225,7 @@
fwrite(*str, sizeof(**str), str.length(), stdout);
printf("\n");
}
+#if !defined(V8_SHARED)
} else {
Context::Scope context_scope(utility_context_);
Handle<Object> global = utility_context_->Global();
@@ -233,6 +236,7 @@
fwrite(*str, sizeof(**str), str.length(), stdout);
printf("\n");
}
+#endif
}
return true;
}
diff --git a/src/global-handles.cc b/src/global-handles.cc
index a6347bb..14c00f1 100644
--- a/src/global-handles.cc
+++ b/src/global-handles.cc
@@ -83,7 +83,6 @@
set_partially_dependent(false);
set_in_new_space_list(false);
parameter_or_next_free_.next_free = NULL;
- weak_reference_callback_ = NULL;
near_death_callback_ = NULL;
}
#endif
@@ -105,7 +104,6 @@
set_partially_dependent(false);
set_state(NORMAL);
parameter_or_next_free_.parameter = NULL;
- weak_reference_callback_ = NULL;
near_death_callback_ = NULL;
IncreaseBlockUses(global_handles);
}
@@ -120,7 +118,6 @@
class_id_ = v8::HeapProfiler::kPersistentHandleNoClassId;
set_independent(false);
set_partially_dependent(false);
- weak_reference_callback_ = NULL;
near_death_callback_ = NULL;
#endif
parameter_or_next_free_.next_free = global_handles->first_free_;
@@ -235,8 +232,14 @@
ASSERT(state() != FREE);
set_state(WEAK);
set_parameter(parameter);
- weak_reference_callback_ = weak_reference_callback;
- near_death_callback_ = near_death_callback;
+ if (weak_reference_callback != NULL) {
+ flags_ = IsWeakCallback::update(flags_, true);
+ near_death_callback_ =
+ reinterpret_cast<NearDeathCallback>(weak_reference_callback);
+ } else {
+ flags_ = IsWeakCallback::update(flags_, false);
+ near_death_callback_ = near_death_callback;
+ }
}
void ClearWeakness(GlobalHandles* global_handles) {
@@ -248,8 +251,7 @@
bool PostGarbageCollectionProcessing(Isolate* isolate,
GlobalHandles* global_handles) {
if (state() != Node::PENDING) return false;
- if (weak_reference_callback_ == NULL &&
- near_death_callback_ == NULL) {
+ if (near_death_callback_ == NULL) {
Release(global_handles);
return false;
}
@@ -267,13 +269,16 @@
ExternalTwoByteString::cast(object_)->resource() != NULL);
// Leaving V8.
VMState state(isolate, EXTERNAL);
- if (weak_reference_callback_ != NULL) {
- weak_reference_callback_(object, par);
- }
if (near_death_callback_ != NULL) {
- near_death_callback_(reinterpret_cast<v8::Isolate*>(isolate),
- object,
- par);
+ if (IsWeakCallback::decode(flags_)) {
+ WeakReferenceCallback callback =
+ reinterpret_cast<WeakReferenceCallback>(near_death_callback_);
+ callback(object, par);
+ } else {
+ near_death_callback_(reinterpret_cast<v8::Isolate*>(isolate),
+ object,
+ par);
+ }
}
}
// Absence of explicit cleanup or revival of weak handle
@@ -306,11 +311,11 @@
class IsIndependent: public BitField<bool, 4, 1> {};
class IsPartiallyDependent: public BitField<bool, 5, 1> {};
class IsInNewSpaceList: public BitField<bool, 6, 1> {};
+ class IsWeakCallback: public BitField<bool, 7, 1> {};
uint8_t flags_;
- // Handle specific callback.
- WeakReferenceCallback weak_reference_callback_;
+ // Handle specific callback - might be a weak reference in disguise.
NearDeathCallback near_death_callback_;
// Provided data for callback. In FREE state, this is used for
@@ -481,8 +486,7 @@
void* parameter,
WeakReferenceCallback weak_reference_callback,
NearDeathCallback near_death_callback) {
- ASSERT((weak_reference_callback != NULL) !=
- (near_death_callback != NULL));
+ ASSERT(near_death_callback != NULL);
Node::FromLocation(location)->MakeWeak(this,
parameter,
weak_reference_callback,
diff --git a/src/heap.cc b/src/heap.cc
index 67759e6..3cf23d0 100644
--- a/src/heap.cc
+++ b/src/heap.cc
@@ -1854,7 +1854,7 @@
HEAP_PROFILE(heap, ObjectMoveEvent(source->address(), target->address()));
Isolate* isolate = heap->isolate();
if (isolate->logger()->is_logging_code_events() ||
- CpuProfiler::is_profiling(isolate)) {
+ isolate->cpu_profiler()->is_profiling()) {
if (target->IsSharedFunctionInfo()) {
PROFILE(isolate, SharedFunctionInfoMoveEvent(
source->address(), target->address()));
@@ -2110,7 +2110,7 @@
void Heap::SelectScavengingVisitorsTable() {
bool logging_and_profiling =
isolate()->logger()->is_logging() ||
- CpuProfiler::is_profiling(isolate()) ||
+ isolate()->cpu_profiler()->is_profiling() ||
(isolate()->heap_profiler() != NULL &&
isolate()->heap_profiler()->is_profiling());
@@ -3805,6 +3805,8 @@
}
// Allow self references to created code object by patching the handle to
// point to the newly allocated Code object.
+ CHECK(code->IsCode());
+ CHECK(code->relocation_info()->IsByteArray());
if (!self_reference.is_null()) {
*(self_reference.location()) = code;
}
@@ -3813,6 +3815,8 @@
// that are dereferenced during the copy to point directly to the actual heap
// objects. These pointers can include references to the code object itself,
// through the self_reference parameter.
+ CHECK(code->IsCode());
+ CHECK(code->relocation_info()->IsByteArray());
code->CopyFrom(desc);
#ifdef VERIFY_HEAP
diff --git a/src/hydrogen-instructions.cc b/src/hydrogen-instructions.cc
index 2aab369..fc80748 100644
--- a/src/hydrogen-instructions.cc
+++ b/src/hydrogen-instructions.cc
@@ -174,7 +174,7 @@
int offset,
int scale) {
if (this == other) {
- return NumericRelation::Eq().Implies(relation);
+ return scale == 0 && relation.IsExtendable(offset);
}
// Test the direct relation.
diff --git a/src/isolate.cc b/src/isolate.cc
index 632ecdc..5d4bc89 100644
--- a/src/isolate.cc
+++ b/src/isolate.cc
@@ -1678,6 +1678,7 @@
date_cache_(NULL),
code_stub_interface_descriptors_(NULL),
context_exit_happened_(false),
+ cpu_profiler_(NULL),
deferred_handles_head_(NULL),
optimizing_compiler_thread_(this),
marking_thread_(NULL),
@@ -1810,7 +1811,9 @@
PreallocatedMemoryThreadStop();
HeapProfiler::TearDown();
- CpuProfiler::TearDown();
+ delete cpu_profiler_;
+ cpu_profiler_ = NULL;
+
if (runtime_profiler_ != NULL) {
runtime_profiler_->TearDown();
delete runtime_profiler_;
@@ -2039,7 +2042,7 @@
// Enable logging before setting up the heap
logger_->SetUp();
- CpuProfiler::SetUp();
+ cpu_profiler_ = new CpuProfiler(this);
HeapProfiler::SetUp();
// Initialize other runtime facilities
diff --git a/src/isolate.h b/src/isolate.h
index d6770cc..ad0b260 100644
--- a/src/isolate.h
+++ b/src/isolate.h
@@ -357,9 +357,6 @@
V(FunctionInfoListener*, active_function_info_listener, NULL) \
/* State for Relocatable. */ \
V(Relocatable*, relocatable_top, NULL) \
- /* State for CodeEntry in profile-generator. */ \
- V(CodeGenerator*, current_code_generator, NULL) \
- V(bool, jump_target_compiling_deferred_code, false) \
V(DebugObjectCache*, string_stream_debug_object_cache, NULL) \
V(Object*, string_stream_current_security_token, NULL) \
/* TODO(isolates): Release this on destruction? */ \
@@ -371,7 +368,6 @@
V(unsigned, ast_node_count, 0) \
/* SafeStackFrameIterator activations count. */ \
V(int, safe_stack_iterator_counter, 0) \
- V(CpuProfiler*, cpu_profiler, NULL) \
V(HeapProfiler*, heap_profiler, NULL) \
V(bool, observer_delivery_pending, false) \
V(HStatistics*, hstatistics, NULL) \
@@ -979,6 +975,8 @@
inline bool IsDebuggerActive();
inline bool DebuggerHasBreakPoints();
+ CpuProfiler* cpu_profiler() const { return cpu_profiler_; }
+
#ifdef DEBUG
HistogramInfo* heap_histograms() { return heap_histograms_; }
@@ -1314,6 +1312,7 @@
Debugger* debugger_;
Debug* debug_;
#endif
+ CpuProfiler* cpu_profiler_;
#define GLOBAL_BACKING_STORE(type, name, initialvalue) \
type name##_;
diff --git a/src/log.cc b/src/log.cc
index 4ec981c..e9ef382 100644
--- a/src/log.cc
+++ b/src/log.cc
@@ -1615,7 +1615,7 @@
tag = Logger::KEYED_CALL_IC_TAG;
break;
}
- PROFILE(ISOLATE, CodeCreateEvent(tag, code_object, description));
+ PROFILE(isolate_, CodeCreateEvent(tag, code_object, description));
}
}
@@ -1719,20 +1719,20 @@
Handle<String> script_name(String::cast(script->name()));
int line_num = GetScriptLineNumber(script, shared->start_position());
if (line_num > 0) {
- PROFILE(ISOLATE,
+ PROFILE(isolate_,
CodeCreateEvent(
Logger::ToNativeByScript(Logger::LAZY_COMPILE_TAG, *script),
*code, *shared,
*script_name, line_num + 1));
} else {
// Can't distinguish eval and script here, so always use Script.
- PROFILE(ISOLATE,
+ PROFILE(isolate_,
CodeCreateEvent(
Logger::ToNativeByScript(Logger::SCRIPT_TAG, *script),
*code, *shared, *script_name));
}
} else {
- PROFILE(ISOLATE,
+ PROFILE(isolate_,
CodeCreateEvent(
Logger::ToNativeByScript(Logger::LAZY_COMPILE_TAG, *script),
*code, *shared, *func_name));
@@ -1745,10 +1745,10 @@
CallHandlerInfo* call_data = CallHandlerInfo::cast(raw_call_data);
Object* callback_obj = call_data->callback();
Address entry_point = v8::ToCData<Address>(callback_obj);
- PROFILE(ISOLATE, CallbackEvent(*func_name, entry_point));
+ PROFILE(isolate_, CallbackEvent(*func_name, entry_point));
}
} else {
- PROFILE(ISOLATE,
+ PROFILE(isolate_,
CodeCreateEvent(
Logger::LAZY_COMPILE_TAG, *code, *shared, *func_name));
}
@@ -1789,11 +1789,11 @@
Address getter_entry = v8::ToCData<Address>(ai->getter());
Name* name = Name::cast(ai->name());
if (getter_entry != 0) {
- PROFILE(ISOLATE, GetterCallbackEvent(name, getter_entry));
+ PROFILE(isolate_, GetterCallbackEvent(name, getter_entry));
}
Address setter_entry = v8::ToCData<Address>(ai->setter());
if (setter_entry != 0) {
- PROFILE(ISOLATE, SetterCallbackEvent(name, setter_entry));
+ PROFILE(isolate_, SetterCallbackEvent(name, setter_entry));
}
}
}
diff --git a/src/mips/builtins-mips.cc b/src/mips/builtins-mips.cc
index 2facd13..54efd94 100644
--- a/src/mips/builtins-mips.cc
+++ b/src/mips/builtins-mips.cc
@@ -128,12 +128,8 @@
if (initial_capacity > 0) {
size += FixedArray::SizeFor(initial_capacity);
}
- __ AllocateInNewSpace(size,
- result,
- scratch2,
- scratch3,
- gc_required,
- TAG_OBJECT);
+ __ Allocate(size, result, scratch2, scratch3, gc_required, TAG_OBJECT);
+
// Allocated the JSArray. Now initialize the fields except for the elements
// array.
// result: JSObject
@@ -665,12 +661,12 @@
// -----------------------------------
Label gc_required;
- __ AllocateInNewSpace(JSValue::kSize,
- v0, // Result.
- a3, // Scratch.
- t0, // Scratch.
- &gc_required,
- TAG_OBJECT);
+ __ Allocate(JSValue::kSize,
+ v0, // Result.
+ a3, // Scratch.
+ t0, // Scratch.
+ &gc_required,
+ TAG_OBJECT);
// Initialising the String Object.
Register map = a3;
diff --git a/src/mips/code-stubs-mips.cc b/src/mips/code-stubs-mips.cc
index f398a4d..f5908d3 100644
--- a/src/mips/code-stubs-mips.cc
+++ b/src/mips/code-stubs-mips.cc
@@ -168,12 +168,7 @@
__ pop(a3);
// Attempt to allocate new JSFunction in new space.
- __ AllocateInNewSpace(JSFunction::kSize,
- v0,
- a1,
- a2,
- &gc,
- TAG_OBJECT);
+ __ Allocate(JSFunction::kSize, v0, a1, a2, &gc, TAG_OBJECT);
__ IncrementCounter(counters->fast_new_closure_total(), 1, t2, t3);
@@ -300,12 +295,7 @@
int length = slots_ + Context::MIN_CONTEXT_SLOTS;
// Attempt to allocate the context in new space.
- __ AllocateInNewSpace(FixedArray::SizeFor(length),
- v0,
- a1,
- a2,
- &gc,
- TAG_OBJECT);
+ __ Allocate(FixedArray::SizeFor(length), v0, a1, a2, &gc, TAG_OBJECT);
// Load the function from the stack.
__ lw(a3, MemOperand(sp, 0));
@@ -349,8 +339,7 @@
// Try to allocate the context in new space.
Label gc;
int length = slots_ + Context::MIN_CONTEXT_SLOTS;
- __ AllocateInNewSpace(FixedArray::SizeFor(length),
- v0, a1, a2, &gc, TAG_OBJECT);
+ __ Allocate(FixedArray::SizeFor(length), v0, a1, a2, &gc, TAG_OBJECT);
// Load the function from the stack.
__ lw(a3, MemOperand(sp, 0));
@@ -429,12 +418,7 @@
// Allocate both the JS array and the elements array in one big
// allocation. This avoids multiple limit checks.
- __ AllocateInNewSpace(size,
- v0,
- a1,
- a2,
- fail,
- TAG_OBJECT);
+ __ Allocate(size, v0, a1, a2, fail, TAG_OBJECT);
if (allocation_site_mode == TRACK_ALLOCATION_SITE) {
__ li(a2, Operand(Handle<Map>(masm->isolate()->heap()->
diff --git a/src/mips/full-codegen-mips.cc b/src/mips/full-codegen-mips.cc
index 056e2ee..bacec10 100644
--- a/src/mips/full-codegen-mips.cc
+++ b/src/mips/full-codegen-mips.cc
@@ -1553,7 +1553,7 @@
__ bind(&materialized);
int size = JSRegExp::kSize + JSRegExp::kInObjectFieldCount * kPointerSize;
Label allocated, runtime_allocate;
- __ AllocateInNewSpace(size, v0, a2, a3, &runtime_allocate, TAG_OBJECT);
+ __ Allocate(size, v0, a2, a3, &runtime_allocate, TAG_OBJECT);
__ jmp(&allocated);
__ bind(&runtime_allocate);
diff --git a/src/mips/lithium-codegen-mips.cc b/src/mips/lithium-codegen-mips.cc
index a16f5ed..cd48934 100644
--- a/src/mips/lithium-codegen-mips.cc
+++ b/src/mips/lithium-codegen-mips.cc
@@ -4005,6 +4005,13 @@
}
+void LCodeGen::DoInnerAllocatedObject(LInnerAllocatedObject* instr) {
+ Register result = ToRegister(instr->result());
+ Register base = ToRegister(instr->base_object());
+ __ Addu(result, base, Operand(instr->offset()));
+}
+
+
void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) {
Register object = ToRegister(instr->object());
Register value = ToRegister(instr->value());
@@ -5255,12 +5262,8 @@
// the constructor's prototype changes, but instance size and property
// counts remain unchanged (if slack tracking finished).
ASSERT(!constructor->shared()->IsInobjectSlackTrackingInProgress());
- __ AllocateInNewSpace(instance_size,
- result,
- scratch,
- scratch2,
- deferred->entry(),
- TAG_OBJECT);
+ __ Allocate(instance_size, result, scratch, scratch2, deferred->entry(),
+ TAG_OBJECT);
__ bind(deferred->exit());
if (FLAG_debug_code) {
@@ -5335,12 +5338,10 @@
}
if (instr->size()->IsConstantOperand()) {
int32_t size = ToInteger32(LConstantOperand::cast(instr->size()));
- __ AllocateInNewSpace(size,
- result,
- scratch,
- scratch2,
- deferred->entry(),
- flags);
+ if (instr->hydrogen()->CanAllocateInOldPointerSpace()) {
+ flags = static_cast<AllocationFlags>(flags | PRETENURE_OLD_POINTER_SPACE);
+ }
+ __ Allocate(size, result, scratch, scratch2, deferred->entry(), flags);
} else {
Register size = ToRegister(instr->size());
__ AllocateInNewSpace(size,
@@ -5575,7 +5576,7 @@
// Allocate all objects that are part of the literal in one big
// allocation. This avoids multiple limit checks.
Label allocated, runtime_allocate;
- __ AllocateInNewSpace(size, v0, a2, a3, &runtime_allocate, TAG_OBJECT);
+ __ Allocate(size, v0, a2, a3, &runtime_allocate, TAG_OBJECT);
__ jmp(&allocated);
__ bind(&runtime_allocate);
@@ -5658,7 +5659,7 @@
int size = JSRegExp::kSize + JSRegExp::kInObjectFieldCount * kPointerSize;
Label allocated, runtime_allocate;
- __ AllocateInNewSpace(size, v0, a2, a3, &runtime_allocate, TAG_OBJECT);
+ __ Allocate(size, v0, a2, a3, &runtime_allocate, TAG_OBJECT);
__ jmp(&allocated);
__ bind(&runtime_allocate);
diff --git a/src/mips/lithium-mips.cc b/src/mips/lithium-mips.cc
index 31d1067..8848032 100644
--- a/src/mips/lithium-mips.cc
+++ b/src/mips/lithium-mips.cc
@@ -290,6 +290,13 @@
}
+void LInnerAllocatedObject::PrintDataTo(StringStream* stream) {
+ stream->Add(" = ");
+ base_object()->PrintTo(stream);
+ stream->Add(" + %d", offset());
+}
+
+
void LCallConstantFunction::PrintDataTo(StringStream* stream) {
stream->Add("#%d / ", arity());
}
@@ -1020,6 +1027,15 @@
}
+LInstruction* LChunkBuilder::DoInnerAllocatedObject(
+ HInnerAllocatedObject* inner_object) {
+ LOperand* base_object = UseRegisterAtStart(inner_object->base_object());
+ LInnerAllocatedObject* result =
+ new(zone()) LInnerAllocatedObject(base_object);
+ return DefineAsRegister(result);
+}
+
+
LInstruction* LChunkBuilder::DoThisFunction(HThisFunction* instr) {
return instr->HasNoUses()
? NULL
diff --git a/src/mips/lithium-mips.h b/src/mips/lithium-mips.h
index ccaad71..80635c3 100644
--- a/src/mips/lithium-mips.h
+++ b/src/mips/lithium-mips.h
@@ -188,7 +188,9 @@
V(LoadFieldByIndex) \
V(DateField) \
V(WrapReceiver) \
- V(Drop)
+ V(Drop) \
+ V(InnerAllocatedObject)
+
#define DECLARE_CONCRETE_INSTRUCTION(type, mnemonic) \
virtual Opcode opcode() const { return LInstruction::k##type; } \
@@ -1600,6 +1602,22 @@
};
+class LInnerAllocatedObject: public LTemplateInstruction<1, 1, 0> {
+ public:
+ explicit LInnerAllocatedObject(LOperand* base_object) {
+ inputs_[0] = base_object;
+ }
+
+ LOperand* base_object() { return inputs_[0]; }
+ int offset() { return hydrogen()->offset(); }
+
+ virtual void PrintDataTo(StringStream* stream);
+
+ DECLARE_CONCRETE_INSTRUCTION(InnerAllocatedObject, "sub-allocated-object")
+ DECLARE_HYDROGEN_ACCESSOR(InnerAllocatedObject)
+};
+
+
class LThisFunction: public LTemplateInstruction<1, 0, 0> {
public:
DECLARE_CONCRETE_INSTRUCTION(ThisFunction, "this-function")
diff --git a/src/mips/macro-assembler-mips.cc b/src/mips/macro-assembler-mips.cc
index af436b6..603f1be 100644
--- a/src/mips/macro-assembler-mips.cc
+++ b/src/mips/macro-assembler-mips.cc
@@ -2912,12 +2912,12 @@
}
-void MacroAssembler::AllocateInNewSpace(int object_size,
- Register result,
- Register scratch1,
- Register scratch2,
- Label* gc_required,
- AllocationFlags flags) {
+void MacroAssembler::Allocate(int object_size,
+ Register result,
+ Register scratch1,
+ Register scratch2,
+ Label* gc_required,
+ AllocationFlags flags) {
if (!FLAG_inline_new) {
if (emit_debug_code()) {
// Trash the registers to simulate an allocation failure.
@@ -2945,20 +2945,21 @@
// Check relative positions of allocation top and limit addresses.
// ARM adds additional checks to make sure the ldm instruction can be
// used. On MIPS we don't have ldm so we don't need additional checks either.
- ExternalReference new_space_allocation_top =
- ExternalReference::new_space_allocation_top_address(isolate());
- ExternalReference new_space_allocation_limit =
- ExternalReference::new_space_allocation_limit_address(isolate());
+ ExternalReference allocation_top =
+ AllocationUtils::GetAllocationTopReference(isolate(), flags);
+ ExternalReference allocation_limit =
+ AllocationUtils::GetAllocationLimitReference(isolate(), flags);
+
intptr_t top =
- reinterpret_cast<intptr_t>(new_space_allocation_top.address());
+ reinterpret_cast<intptr_t>(allocation_top.address());
intptr_t limit =
- reinterpret_cast<intptr_t>(new_space_allocation_limit.address());
+ reinterpret_cast<intptr_t>(allocation_limit.address());
ASSERT((limit - top) == kPointerSize);
// Set up allocation top address and object size registers.
Register topaddr = scratch1;
Register obj_size_reg = scratch2;
- li(topaddr, Operand(new_space_allocation_top));
+ li(topaddr, Operand(allocation_top));
li(obj_size_reg, Operand(object_size));
// This code stores a temporary value in t9.
@@ -2997,6 +2998,7 @@
Register scratch2,
Label* gc_required,
AllocationFlags flags) {
+ ASSERT((flags & PRETENURE_OLD_POINTER_SPACE) == 0);
if (!FLAG_inline_new) {
if (emit_debug_code()) {
// Trash the registers to simulate an allocation failure.
@@ -3159,12 +3161,8 @@
Register scratch1,
Register scratch2,
Label* gc_required) {
- AllocateInNewSpace(ConsString::kSize,
- result,
- scratch1,
- scratch2,
- gc_required,
- TAG_OBJECT);
+ Allocate(ConsString::kSize, result, scratch1, scratch2, gc_required,
+ TAG_OBJECT);
InitializeNewString(result,
length,
Heap::kConsStringMapRootIndex,
@@ -3178,12 +3176,8 @@
Register scratch1,
Register scratch2,
Label* gc_required) {
- AllocateInNewSpace(ConsString::kSize,
- result,
- scratch1,
- scratch2,
- gc_required,
- TAG_OBJECT);
+ Allocate(ConsString::kSize, result, scratch1, scratch2, gc_required,
+ TAG_OBJECT);
InitializeNewString(result,
length,
Heap::kConsAsciiStringMapRootIndex,
@@ -3197,12 +3191,8 @@
Register scratch1,
Register scratch2,
Label* gc_required) {
- AllocateInNewSpace(SlicedString::kSize,
- result,
- scratch1,
- scratch2,
- gc_required,
- TAG_OBJECT);
+ Allocate(SlicedString::kSize, result, scratch1, scratch2, gc_required,
+ TAG_OBJECT);
InitializeNewString(result,
length,
@@ -3217,12 +3207,8 @@
Register scratch1,
Register scratch2,
Label* gc_required) {
- AllocateInNewSpace(SlicedString::kSize,
- result,
- scratch1,
- scratch2,
- gc_required,
- TAG_OBJECT);
+ Allocate(SlicedString::kSize, result, scratch1, scratch2, gc_required,
+ TAG_OBJECT);
InitializeNewString(result,
length,
@@ -3242,13 +3228,8 @@
TaggingMode tagging_mode) {
// Allocate an object in the heap for the heap number and tag it as a heap
// object.
- AllocateInNewSpace(HeapNumber::kSize,
- result,
- scratch1,
- scratch2,
- need_gc,
- tagging_mode == TAG_RESULT ? TAG_OBJECT :
- NO_ALLOCATION_FLAGS);
+ Allocate(HeapNumber::kSize, result, scratch1, scratch2, need_gc,
+ tagging_mode == TAG_RESULT ? TAG_OBJECT : NO_ALLOCATION_FLAGS);
// Store heap number map in the allocated object.
AssertRegisterIsRoot(heap_number_map, Heap::kHeapNumberMapRootIndex);
diff --git a/src/mips/macro-assembler-mips.h b/src/mips/macro-assembler-mips.h
index 563c0dd..e4cf3bc 100644
--- a/src/mips/macro-assembler-mips.h
+++ b/src/mips/macro-assembler-mips.h
@@ -477,19 +477,20 @@
// ---------------------------------------------------------------------------
// Allocation support.
- // Allocate an object in new space. The object_size is specified
- // either in bytes or in words if the allocation flag SIZE_IN_WORDS
- // is passed. If the new space is exhausted control continues at the
- // gc_required label. The allocated object is returned in result. If
- // the flag tag_allocated_object is true the result is tagged as as
- // a heap object. All registers are clobbered also when control
- // continues at the gc_required label.
- void AllocateInNewSpace(int object_size,
- Register result,
- Register scratch1,
- Register scratch2,
- Label* gc_required,
- AllocationFlags flags);
+ // Allocate an object in new space or old pointer space. The object_size is
+ // specified either in bytes or in words if the allocation flag SIZE_IN_WORDS
+ // is passed. If the space is exhausted control continues at the gc_required
+ // label. The allocated object is returned in result. If the flag
+ // tag_allocated_object is true the result is tagged as as a heap object.
+ // All registers are clobbered also when control continues at the gc_required
+ // label.
+ void Allocate(int object_size,
+ Register result,
+ Register scratch1,
+ Register scratch2,
+ Label* gc_required,
+ AllocationFlags flags);
+
void AllocateInNewSpace(Register object_size,
Register result,
Register scratch1,
diff --git a/src/mips/stub-cache-mips.cc b/src/mips/stub-cache-mips.cc
index 959da8e..d5cf6de 100644
--- a/src/mips/stub-cache-mips.cc
+++ b/src/mips/stub-cache-mips.cc
@@ -2604,27 +2604,22 @@
Handle<Code> StoreStubCompiler::CompileStoreCallback(
Handle<Name> name,
- Handle<JSObject> receiver,
+ Handle<JSObject> object,
Handle<JSObject> holder,
Handle<ExecutableAccessorInfo> callback) {
- // ----------- S t a t e -------------
- // -- a0 : value
- // -- a1 : receiver
- // -- a2 : name
- // -- ra : return address
- // -----------------------------------
Label miss;
// Check that the maps haven't changed.
- __ JumpIfSmi(a1, &miss, a3);
- CheckPrototypes(receiver, a1, holder, a3, t0, t1, name, &miss);
+ __ JumpIfSmi(receiver(), &miss);
+ CheckPrototypes(object, receiver(), holder,
+ scratch1(), scratch2(), scratch3(), name, &miss);
// Stub never generated for non-global objects that require access
// checks.
ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded());
- __ push(a1); // Receiver.
- __ li(a3, Operand(callback)); // Callback info.
- __ Push(a3, a2, a0);
+ __ push(receiver()); // Receiver.
+ __ li(at, Operand(callback)); // Callback info.
+ __ Push(at, this->name(), value());
// Do tail-call to the runtime system.
ExternalReference store_callback_property =
@@ -2687,61 +2682,28 @@
#define __ ACCESS_MASM(masm())
-Handle<Code> StoreStubCompiler::CompileStoreViaSetter(
- Handle<Name> name,
- Handle<JSObject> receiver,
- Handle<JSObject> holder,
- Handle<JSFunction> setter) {
- // ----------- S t a t e -------------
- // -- a0 : value
- // -- a1 : receiver
- // -- a2 : name
- // -- ra : return address
- // -----------------------------------
- Label miss;
-
- // Check that the maps haven't changed.
- __ JumpIfSmi(a1, &miss);
- CheckPrototypes(receiver, a1, holder, a3, t0, t1, name, &miss);
-
- GenerateStoreViaSetter(masm(), setter);
-
- __ bind(&miss);
- TailCallBuiltin(masm(), MissBuiltin(kind()));
-
- // Return the generated code.
- return GetICCode(kind(), Code::CALLBACKS, name);
-}
-
-
Handle<Code> StoreStubCompiler::CompileStoreInterceptor(
- Handle<JSObject> receiver,
+ Handle<JSObject> object,
Handle<Name> name) {
- // ----------- S t a t e -------------
- // -- a0 : value
- // -- a1 : receiver
- // -- a2 : name
- // -- ra : return address
- // -----------------------------------
Label miss;
// Check that the map of the object hasn't changed.
- __ CheckMap(a1, a3, Handle<Map>(receiver->map()), &miss,
+ __ CheckMap(receiver(), scratch1(), Handle<Map>(object->map()), &miss,
DO_SMI_CHECK, ALLOW_ELEMENT_TRANSITION_MAPS);
// Perform global security token check if needed.
- if (receiver->IsJSGlobalProxy()) {
- __ CheckAccessGlobalProxy(a1, a3, &miss);
+ if (object->IsJSGlobalProxy()) {
+ __ CheckAccessGlobalProxy(receiver(), scratch1(), &miss);
}
// Stub is never generated for non-global objects that require access
// checks.
- ASSERT(receiver->IsJSGlobalProxy() || !receiver->IsAccessCheckNeeded());
+ ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded());
- __ Push(a1, a2, a0); // Receiver, name, value.
+ __ Push(receiver(), this->name(), value());
- __ li(a0, Operand(Smi::FromInt(strict_mode())));
- __ push(a0); // Strict mode.
+ __ li(scratch1(), Operand(Smi::FromInt(strict_mode())));
+ __ push(scratch1()); // strict mode
// Do tail-call to the runtime system.
ExternalReference store_ic_property =
@@ -2762,39 +2724,37 @@
Handle<GlobalObject> object,
Handle<JSGlobalPropertyCell> cell,
Handle<Name> name) {
- // ----------- S t a t e -------------
- // -- a0 : value
- // -- a1 : receiver
- // -- a2 : name
- // -- ra : return address
- // -----------------------------------
Label miss;
// Check that the map of the global has not changed.
- __ lw(a3, FieldMemOperand(a1, HeapObject::kMapOffset));
- __ Branch(&miss, ne, a3, Operand(Handle<Map>(object->map())));
+ __ lw(scratch1(), FieldMemOperand(receiver(), HeapObject::kMapOffset));
+ __ Branch(&miss, ne, scratch1(), Operand(Handle<Map>(object->map())));
// Check that the value in the cell is not the hole. If it is, this
// cell could have been deleted and reintroducing the global needs
// to update the property details in the property dictionary of the
// global object. We bail out to the runtime system to do that.
- __ li(t0, Operand(cell));
- __ LoadRoot(t1, Heap::kTheHoleValueRootIndex);
- __ lw(t2, FieldMemOperand(t0, JSGlobalPropertyCell::kValueOffset));
- __ Branch(&miss, eq, t1, Operand(t2));
+ __ li(scratch1(), Operand(cell));
+ __ LoadRoot(scratch2(), Heap::kTheHoleValueRootIndex);
+ __ lw(scratch3(),
+ FieldMemOperand(scratch1(), JSGlobalPropertyCell::kValueOffset));
+ __ Branch(&miss, eq, scratch3(), Operand(scratch2()));
// Store the value in the cell.
- __ sw(a0, FieldMemOperand(t0, JSGlobalPropertyCell::kValueOffset));
+ __ sw(value(),
+ FieldMemOperand(scratch1(), JSGlobalPropertyCell::kValueOffset));
__ mov(v0, a0); // Stored value must be returned in v0.
// Cells are always rescanned, so no write barrier here.
Counters* counters = masm()->isolate()->counters();
- __ IncrementCounter(counters->named_store_global_inline(), 1, a1, a3);
+ __ IncrementCounter(
+ counters->named_store_global_inline(), 1, scratch1(), scratch2());
__ Ret();
// Handle store cache miss.
__ bind(&miss);
- __ IncrementCounter(counters->named_store_global_inline_miss(), 1, a1, a3);
+ __ IncrementCounter(
+ counters->named_store_global_inline_miss(), 1, scratch1(), scratch2());
TailCallBuiltin(masm(), MissBuiltin(kind()));
// Return the generated code.
@@ -2936,33 +2896,6 @@
}
-Handle<Code> KeyedLoadStubCompiler::CompileLoadElement(
- Handle<Map> receiver_map) {
- // ----------- S t a t e -------------
- // -- ra : return address
- // -- a0 : key
- // -- a1 : receiver
- // -----------------------------------
- ElementsKind elements_kind = receiver_map->elements_kind();
- if (receiver_map->has_fast_elements() ||
- receiver_map->has_external_array_elements()) {
- Handle<Code> stub = KeyedLoadFastElementStub(
- receiver_map->instance_type() == JS_ARRAY_TYPE,
- elements_kind).GetCode(isolate());
- __ DispatchMap(a1, a2, receiver_map, stub, DO_SMI_CHECK);
- } else {
- Handle<Code> stub =
- KeyedLoadDictionaryElementStub().GetCode(isolate());
- __ DispatchMap(a1, a2, receiver_map, stub, DO_SMI_CHECK);
- }
-
- TailCallBuiltin(masm(), MissBuiltin(kind()));
-
- // Return the generated code.
- return GetICCode(kind(), Code::NORMAL, factory()->empty_string());
-}
-
-
Handle<Code> BaseLoadStubCompiler::CompilePolymorphicIC(
MapHandleList* receiver_maps,
CodeHandleList* handlers,
@@ -2995,55 +2928,23 @@
}
-Handle<Code> KeyedStoreStubCompiler::CompileStoreElement(
- Handle<Map> receiver_map) {
- // ----------- S t a t e -------------
- // -- a0 : value
- // -- a1 : key
- // -- a2 : receiver
- // -- ra : return address
- // -- a3 : scratch
- // -----------------------------------
- ElementsKind elements_kind = receiver_map->elements_kind();
- bool is_js_array = receiver_map->instance_type() == JS_ARRAY_TYPE;
- Handle<Code> stub =
- KeyedStoreElementStub(is_js_array,
- elements_kind,
- store_mode_).GetCode(isolate());
-
- __ DispatchMap(a2, a3, receiver_map, stub, DO_SMI_CHECK);
-
- TailCallBuiltin(masm(), MissBuiltin(kind()));
-
- // Return the generated code.
- return GetICCode(kind(), Code::NORMAL, factory()->empty_string());
-}
-
-
Handle<Code> KeyedStoreStubCompiler::CompileStorePolymorphic(
MapHandleList* receiver_maps,
CodeHandleList* handler_stubs,
MapHandleList* transitioned_maps) {
- // ----------- S t a t e -------------
- // -- a0 : value
- // -- a1 : key
- // -- a2 : receiver
- // -- ra : return address
- // -- a3 : scratch
- // -----------------------------------
Label miss;
- __ JumpIfSmi(a2, &miss);
+ __ JumpIfSmi(receiver(), &miss);
int receiver_count = receiver_maps->length();
- __ lw(a3, FieldMemOperand(a2, HeapObject::kMapOffset));
+ __ lw(scratch1(), FieldMemOperand(receiver(), HeapObject::kMapOffset));
for (int i = 0; i < receiver_count; ++i) {
if (transitioned_maps->at(i).is_null()) {
__ Jump(handler_stubs->at(i), RelocInfo::CODE_TARGET, eq,
- a3, Operand(receiver_maps->at(i)));
+ scratch1(), Operand(receiver_maps->at(i)));
} else {
Label next_map;
- __ Branch(&next_map, ne, a3, Operand(receiver_maps->at(i)));
- __ li(a3, Operand(transitioned_maps->at(i)));
+ __ Branch(&next_map, ne, scratch1(), Operand(receiver_maps->at(i)));
+ __ li(transition_map(), Operand(transitioned_maps->at(i)));
__ Jump(handler_stubs->at(i), RelocInfo::CODE_TARGET);
__ bind(&next_map);
}
@@ -3830,8 +3731,7 @@
__ Branch(&check_capacity, ne, elements_reg, Operand(at));
int size = FixedArray::SizeFor(JSArray::kPreallocatedArrayElements);
- __ AllocateInNewSpace(size, elements_reg, scratch, scratch2, &slow,
- TAG_OBJECT);
+ __ Allocate(size, elements_reg, scratch, scratch2, &slow, TAG_OBJECT);
__ LoadRoot(scratch, Heap::kFixedArrayMapRootIndex);
__ sw(scratch, FieldMemOperand(elements_reg, JSObject::kMapOffset));
@@ -3981,8 +3881,7 @@
__ Branch(&check_capacity, ne, elements_reg, Operand(at));
int size = FixedDoubleArray::SizeFor(JSArray::kPreallocatedArrayElements);
- __ AllocateInNewSpace(size, elements_reg, scratch1, scratch2, &slow,
- TAG_OBJECT);
+ __ Allocate(size, elements_reg, scratch1, scratch2, &slow, TAG_OBJECT);
// Initialize the new FixedDoubleArray.
__ LoadRoot(scratch1, Heap::kFixedDoubleArrayMapRootIndex);
diff --git a/src/objects.cc b/src/objects.cc
index 9b7e0a7..00d00d5 100644
--- a/src/objects.cc
+++ b/src/objects.cc
@@ -8813,10 +8813,15 @@
ASSERT(Marking::Color(this) == Marking::WHITE_OBJECT);
// copy code
+ CHECK(IsCode());
+ CHECK(relocation_info()->IsByteArray());
+ CHECK(reinterpret_cast<intptr_t>(instruction_start()) ==
+ reinterpret_cast<intptr_t>(this) + Code::kHeaderSize - kHeapObjectTag);
memmove(instruction_start(), desc.buffer, desc.instr_size);
// copy reloc info
// TODO(mstarzinger): Remove once we found the bug.
+ CHECK(IsCode());
CHECK(relocation_info()->IsByteArray());
memmove(relocation_start(),
desc.buffer + desc.buffer_size - desc.reloc_size,
diff --git a/src/objects.h b/src/objects.h
index 96a3800..933a075 100644
--- a/src/objects.h
+++ b/src/objects.h
@@ -4299,12 +4299,7 @@
public:
// Opaque data type for encapsulating code flags like kind, inline
// cache state, and arguments count.
- // FLAGS_MIN_VALUE and FLAGS_MAX_VALUE are specified to ensure that
- // enumeration type has correct value range (see Issue 830 for more details).
- enum Flags {
- FLAGS_MIN_VALUE = 0,
- FLAGS_MAX_VALUE = kMaxUInt32
- };
+ typedef uint32_t Flags;
#define CODE_KIND_LIST(V) \
V(FUNCTION) \
diff --git a/src/platform-cygwin.cc b/src/platform-cygwin.cc
index 8914d63..67c389e 100644
--- a/src/platform-cygwin.cc
+++ b/src/platform-cygwin.cc
@@ -687,13 +687,14 @@
CONTEXT context;
memset(&context, 0, sizeof(context));
+ Isolate* isolate = sampler->isolate();
TickSample sample_obj;
- TickSample* sample = CpuProfiler::TickSampleEvent(sampler->isolate());
+ TickSample* sample = isolate->cpu_profiler()->TickSampleEvent();
if (sample == NULL) sample = &sample_obj;
static const DWORD kSuspendFailed = static_cast<DWORD>(-1);
if (SuspendThread(profiled_thread) == kSuspendFailed) return;
- sample->state = sampler->isolate()->current_vm_state();
+ sample->state = isolate->current_vm_state();
context.ContextFlags = CONTEXT_FULL;
if (GetThreadContext(profiled_thread, &context) != 0) {
diff --git a/src/platform-freebsd.cc b/src/platform-freebsd.cc
index 986c5af..14f7171 100644
--- a/src/platform-freebsd.cc
+++ b/src/platform-freebsd.cc
@@ -715,7 +715,7 @@
if (sampler == NULL || !sampler->IsActive()) return;
TickSample sample_obj;
- TickSample* sample = CpuProfiler::TickSampleEvent(isolate);
+ TickSample* sample = isolate->cpu_profiler()->TickSampleEvent();
if (sample == NULL) sample = &sample_obj;
// Extracting the sample from the context is extremely machine dependent.
diff --git a/src/platform-linux.cc b/src/platform-linux.cc
index 0359b2d..d21f160 100644
--- a/src/platform-linux.cc
+++ b/src/platform-linux.cc
@@ -1088,7 +1088,7 @@
if (sampler == NULL || !sampler->IsActive()) return;
TickSample sample_obj;
- TickSample* sample = CpuProfiler::TickSampleEvent(isolate);
+ TickSample* sample = isolate->cpu_profiler()->TickSampleEvent();
if (sample == NULL) sample = &sample_obj;
// Extracting the sample from the context is extremely machine dependent.
diff --git a/src/platform-macos.cc b/src/platform-macos.cc
index fde5217..30e2b89 100644
--- a/src/platform-macos.cc
+++ b/src/platform-macos.cc
@@ -818,8 +818,9 @@
void SampleContext(Sampler* sampler) {
thread_act_t profiled_thread = sampler->platform_data()->profiled_thread();
+ Isolate* isolate = sampler->isolate();
TickSample sample_obj;
- TickSample* sample = CpuProfiler::TickSampleEvent(sampler->isolate());
+ TickSample* sample = isolate->cpu_profiler()->TickSampleEvent();
if (sample == NULL) sample = &sample_obj;
if (KERN_SUCCESS != thread_suspend(profiled_thread)) return;
@@ -850,7 +851,7 @@
flavor,
reinterpret_cast<natural_t*>(&state),
&count) == KERN_SUCCESS) {
- sample->state = sampler->isolate()->current_vm_state();
+ sample->state = isolate->current_vm_state();
sample->pc = reinterpret_cast<Address>(state.REGISTER_FIELD(ip));
sample->sp = reinterpret_cast<Address>(state.REGISTER_FIELD(sp));
sample->fp = reinterpret_cast<Address>(state.REGISTER_FIELD(bp));
diff --git a/src/platform-openbsd.cc b/src/platform-openbsd.cc
index 66eac22..e48d4cb 100644
--- a/src/platform-openbsd.cc
+++ b/src/platform-openbsd.cc
@@ -748,7 +748,7 @@
if (sampler == NULL || !sampler->IsActive()) return;
TickSample sample_obj;
- TickSample* sample = CpuProfiler::TickSampleEvent(isolate);
+ TickSample* sample = isolate->cpu_profiler()->TickSampleEvent();
if (sample == NULL) sample = &sample_obj;
// Extracting the sample from the context is extremely machine dependent.
diff --git a/src/platform-solaris.cc b/src/platform-solaris.cc
index 85ba95f..0e616d1 100644
--- a/src/platform-solaris.cc
+++ b/src/platform-solaris.cc
@@ -682,7 +682,7 @@
if (sampler == NULL || !sampler->IsActive()) return;
TickSample sample_obj;
- TickSample* sample = CpuProfiler::TickSampleEvent(isolate);
+ TickSample* sample = isolate->cpu_profiler()->TickSampleEvent();
if (sample == NULL) sample = &sample_obj;
// Extracting the sample from the context is extremely machine dependent.
diff --git a/src/platform-win32.cc b/src/platform-win32.cc
index 66dbade..c1bae93 100644
--- a/src/platform-win32.cc
+++ b/src/platform-win32.cc
@@ -2064,13 +2064,14 @@
CONTEXT context;
memset(&context, 0, sizeof(context));
+ Isolate* isolate = sampler->isolate();
TickSample sample_obj;
- TickSample* sample = CpuProfiler::TickSampleEvent(sampler->isolate());
+ TickSample* sample = isolate->cpu_profiler()->TickSampleEvent();
if (sample == NULL) sample = &sample_obj;
static const DWORD kSuspendFailed = static_cast<DWORD>(-1);
if (SuspendThread(profiled_thread) == kSuspendFailed) return;
- sample->state = sampler->isolate()->current_vm_state();
+ sample->state = isolate->current_vm_state();
context.ContextFlags = CONTEXT_FULL;
if (GetThreadContext(profiled_thread, &context) != 0) {
diff --git a/src/profile-generator-inl.h b/src/profile-generator-inl.h
index 6e7f499..4e6302c 100644
--- a/src/profile-generator-inl.h
+++ b/src/profile-generator-inl.h
@@ -74,7 +74,8 @@
entry_(entry),
total_ticks_(0),
self_ticks_(0),
- children_(CodeEntriesMatch) {
+ children_(CodeEntriesMatch),
+ id_(tree->next_node_id()) {
}
diff --git a/src/profile-generator.cc b/src/profile-generator.cc
index 2bf1724..ce07213 100644
--- a/src/profile-generator.cc
+++ b/src/profile-generator.cc
@@ -296,6 +296,7 @@
"",
0,
TokenEnumerator::kNoSecurityToken),
+ next_node_id_(1),
root_(new ProfileNode(this, &root_entry_)) {
}
@@ -306,7 +307,7 @@
}
-void ProfileTree::AddPathFromEnd(const Vector<CodeEntry*>& path) {
+ProfileNode* ProfileTree::AddPathFromEnd(const Vector<CodeEntry*>& path) {
ProfileNode* node = root_;
for (CodeEntry** entry = path.start() + path.length() - 1;
entry != path.start() - 1;
@@ -316,6 +317,7 @@
}
}
node->IncrementSelfTicks();
+ return node;
}
@@ -467,7 +469,8 @@
void CpuProfile::AddPath(const Vector<CodeEntry*>& path) {
- top_down_.AddPathFromEnd(path);
+ ProfileNode* top_frame_node = top_down_.AddPathFromEnd(path);
+ if (record_samples_) samples_.Add(top_frame_node);
}
@@ -483,7 +486,7 @@
CpuProfile* CpuProfile::FilteredClone(int security_token_id) {
ASSERT(security_token_id != TokenEnumerator::kNoSecurityToken);
- CpuProfile* clone = new CpuProfile(title_, uid_);
+ CpuProfile* clone = new CpuProfile(title_, uid_, false);
clone->top_down_.FilteredClone(&top_down_, security_token_id);
return clone;
}
@@ -609,7 +612,8 @@
}
-bool CpuProfilesCollection::StartProfiling(const char* title, unsigned uid) {
+bool CpuProfilesCollection::StartProfiling(const char* title, unsigned uid,
+ bool record_samples) {
ASSERT(uid > 0);
current_profiles_semaphore_->Wait();
if (current_profiles_.length() >= kMaxSimultaneousProfiles) {
@@ -623,17 +627,12 @@
return false;
}
}
- current_profiles_.Add(new CpuProfile(title, uid));
+ current_profiles_.Add(new CpuProfile(title, uid, record_samples));
current_profiles_semaphore_->Signal();
return true;
}
-bool CpuProfilesCollection::StartProfiling(String* title, unsigned uid) {
- return StartProfiling(GetName(title), uid);
-}
-
-
CpuProfile* CpuProfilesCollection::StopProfiling(int security_token_id,
const char* title,
double actual_sampling_rate) {
diff --git a/src/profile-generator.h b/src/profile-generator.h
index b128dad..4ddb753 100644
--- a/src/profile-generator.h
+++ b/src/profile-generator.h
@@ -150,6 +150,7 @@
INLINE(const List<ProfileNode*>* children() const) { return &children_list_; }
double GetSelfMillis() const;
double GetTotalMillis() const;
+ unsigned id() const { return id_; }
void Print(int indent);
@@ -170,6 +171,7 @@
// Mapping from CodeEntry* to ProfileNode*
HashMap children_;
List<ProfileNode*> children_list_;
+ unsigned id_;
DISALLOW_COPY_AND_ASSIGN(ProfileNode);
};
@@ -180,7 +182,7 @@
ProfileTree();
~ProfileTree();
- void AddPathFromEnd(const Vector<CodeEntry*>& path);
+ ProfileNode* AddPathFromEnd(const Vector<CodeEntry*>& path);
void AddPathFromStart(const Vector<CodeEntry*>& path);
void CalculateTotalTicks();
void FilteredClone(ProfileTree* src, int security_token_id);
@@ -191,6 +193,8 @@
ProfileNode* root() const { return root_; }
void SetTickRatePerMs(double ticks_per_ms);
+ unsigned next_node_id() { return next_node_id_++; }
+
void ShortPrint();
void Print() {
root_->Print(0);
@@ -201,6 +205,7 @@
void TraverseDepthFirst(Callback* callback);
CodeEntry root_entry_;
+ unsigned next_node_id_;
ProfileNode* root_;
double ms_to_ticks_scale_;
@@ -210,8 +215,8 @@
class CpuProfile {
public:
- CpuProfile(const char* title, unsigned uid)
- : title_(title), uid_(uid) { }
+ CpuProfile(const char* title, unsigned uid, bool record_samples)
+ : title_(title), uid_(uid), record_samples_(record_samples) { }
// Add pc -> ... -> main() call path to the profile.
void AddPath(const Vector<CodeEntry*>& path);
@@ -223,6 +228,9 @@
INLINE(unsigned uid() const) { return uid_; }
INLINE(const ProfileTree* top_down() const) { return &top_down_; }
+ INLINE(int samples_count() const) { return samples_.length(); }
+ INLINE(ProfileNode* sample(int index) const) { return samples_.at(index); }
+
void UpdateTicksScale();
void ShortPrint();
@@ -231,6 +239,8 @@
private:
const char* title_;
unsigned uid_;
+ bool record_samples_;
+ List<ProfileNode*> samples_;
ProfileTree top_down_;
DISALLOW_COPY_AND_ASSIGN(CpuProfile);
@@ -288,8 +298,7 @@
CpuProfilesCollection();
~CpuProfilesCollection();
- bool StartProfiling(const char* title, unsigned uid);
- bool StartProfiling(String* title, unsigned uid);
+ bool StartProfiling(const char* title, unsigned uid, bool record_samples);
CpuProfile* StopProfiling(int security_token_id,
const char* title,
double actual_sampling_rate);
diff --git a/src/runtime.cc b/src/runtime.cc
index 12777e7..e220d6b 100644
--- a/src/runtime.cc
+++ b/src/runtime.cc
@@ -2231,7 +2231,7 @@
target->set_literals(*literals);
if (isolate->logger()->is_logging_code_events() ||
- CpuProfiler::is_profiling(isolate)) {
+ isolate->cpu_profiler()->is_profiling()) {
isolate->logger()->LogExistingFunction(
source_shared, Handle<Code>(source_shared->code()));
}
diff --git a/src/version.cc b/src/version.cc
index 6a62f58..4bb5a49 100644
--- a/src/version.cc
+++ b/src/version.cc
@@ -34,7 +34,7 @@
// cannot be changed without changing the SCons build script.
#define MAJOR_VERSION 3
#define MINOR_VERSION 17
-#define BUILD_NUMBER 12
+#define BUILD_NUMBER 13
#define PATCH_LEVEL 0
// Use 1 for candidates and 0 otherwise.
// (Boolean macro values are not supported by all preprocessors.)