Index: src/api.cc |
diff --git a/src/api.cc b/src/api.cc |
index 014d82ee4f0aab86c5f16ca339c22b335c42753b..c56bc05601e06f20607e0147b0eed429e5e28816 100644 |
--- a/src/api.cc |
+++ b/src/api.cc |
@@ -38,6 +38,7 @@ |
#include "compiler.h" |
#include "conversions-inl.h" |
#include "counters.h" |
+#include "cpu-profiler.h" |
#include "debug.h" |
#include "deoptimizer.h" |
#include "execution.h" |
@@ -297,11 +298,17 @@ static inline bool EmptyCheck(const char* location, const v8::Data* obj) { |
return (obj == 0) ? ReportEmptyHandle(location) : false; |
} |
+ |
// --- S t a t i c s --- |
-static bool InitializeHelper() { |
- if (i::Snapshot::Initialize()) return true; |
+static bool InitializeHelper(i::Isolate* isolate) { |
+ // If the isolate has a function entry hook, it needs to re-build all its |
+ // code stubs with entry hooks embedded, so let's deserialize a snapshot. |
+ if (isolate == NULL || isolate->function_entry_hook() == NULL) { |
+ if (i::Snapshot::Initialize()) |
+ return true; |
+ } |
return i::V8::Initialize(NULL); |
} |
@@ -313,9 +320,10 @@ static inline bool EnsureInitializedForIsolate(i::Isolate* isolate, |
if (isolate->IsInitialized()) return true; |
} |
ASSERT(isolate == i::Isolate::Current()); |
- return ApiCheck(InitializeHelper(), location, "Error initializing V8"); |
+ return ApiCheck(InitializeHelper(isolate), location, "Error initializing V8"); |
} |
+ |
// Some initializing API functions are called early and may be |
// called on a thread different from static initializer thread. |
// If Isolate API is used, Isolate::Enter() will initialize TLS so |
@@ -389,9 +397,13 @@ enum CompressedStartupDataItems { |
kSnapshotContext, |
kLibraries, |
kExperimentalLibraries, |
+#if defined(ENABLE_I18N_SUPPORT) |
+ kI18NExtension, |
+#endif |
kCompressedStartupDataCount |
}; |
+ |
int V8::GetCompressedStartupDataCount() { |
#ifdef COMPRESS_STARTUP_DATA_BZ2 |
return kCompressedStartupDataCount; |
@@ -428,6 +440,17 @@ void V8::GetCompressedStartupData(StartupData* compressed_data) { |
exp_libraries_source.length(); |
compressed_data[kExperimentalLibraries].raw_size = |
i::ExperimentalNatives::GetRawScriptsSize(); |
+ |
+#if defined(ENABLE_I18N_SUPPORT) |
+ i::Vector<const ii:byte> i18n_extension_source = |
+ i::I18NNatives::GetScriptsSource(); |
+ compressed_data[kI18NExtension].data = |
+ reinterpret_cast<const char*>(i18n_extension_source.start()); |
+ compressed_data[kI18NExtension].compressed_size = |
+ i18n_extension_source.length(); |
+ compressed_data[kI18NExtension].raw_size = |
+ i::I18NNatives::GetRawScriptsSize(); |
+#endif |
#endif |
} |
@@ -457,6 +480,15 @@ void V8::SetDecompressedStartupData(StartupData* decompressed_data) { |
decompressed_data[kExperimentalLibraries].data, |
decompressed_data[kExperimentalLibraries].raw_size); |
i::ExperimentalNatives::SetRawScriptsSource(exp_libraries_source); |
+ |
+#if defined(ENABLE_I18N_SUPPORT) |
+ ASSERT_EQ(i::I18NNatives::GetRawScriptsSize(), |
+ decompressed_data[kI18NExtension].raw_size); |
+ i::Vector<const char> i18n_extension_source( |
+ decompressed_data[kI18NExtension].data, |
+ decompressed_data[kI18NExtension].raw_size); |
+ i::I18NNatives::SetRawScriptsSource(i18n_extension_source); |
+#endif |
#endif |
} |
@@ -641,6 +673,7 @@ void V8::DisposeGlobal(i::Object** obj) { |
i::GlobalHandles::Destroy(obj); |
} |
+ |
// --- H a n d l e s --- |
@@ -2087,13 +2120,12 @@ void Script::SetData(v8::Handle<String> data) { |
v8::TryCatch::TryCatch() |
: isolate_(i::Isolate::Current()), |
next_(isolate_->try_catch_handler_address()), |
- exception_(isolate_->heap()->the_hole_value()), |
- message_(i::Smi::FromInt(0)), |
is_verbose_(false), |
can_continue_(true), |
capture_message_(true), |
rethrow_(false), |
has_terminated_(false) { |
+ Reset(); |
isolate_->RegisterTryCatchHandler(this); |
} |
@@ -2103,8 +2135,17 @@ v8::TryCatch::~TryCatch() { |
if (rethrow_) { |
v8::HandleScope scope(reinterpret_cast<Isolate*>(isolate_)); |
v8::Local<v8::Value> exc = v8::Local<v8::Value>::New(Exception()); |
+ if (HasCaught() && capture_message_) { |
+ // If an exception was caught and rethrow_ is indicated, the saved |
+ // message, script, and location need to be restored to Isolate TLS |
+ // for reuse. capture_message_ needs to be disabled so that DoThrow() |
+ // does not create a new message. |
+ isolate_->thread_local_top()->rethrowing_message_ = true; |
+ isolate_->RestorePendingMessageFromTryCatch(this); |
+ } |
isolate_->UnregisterTryCatchHandler(this); |
v8::ThrowException(exc); |
+ ASSERT(!isolate_->thread_local_top()->rethrowing_message_); |
} else { |
isolate_->UnregisterTryCatchHandler(this); |
} |
@@ -2165,8 +2206,9 @@ v8::Local<Value> v8::TryCatch::StackTrace() const { |
v8::Local<v8::Message> v8::TryCatch::Message() const { |
ASSERT(isolate_ == i::Isolate::Current()); |
- if (HasCaught() && message_ != i::Smi::FromInt(0)) { |
- i::Object* message = reinterpret_cast<i::Object*>(message_); |
+ i::Object* message = reinterpret_cast<i::Object*>(message_obj_); |
+ ASSERT(message->IsJSMessageObject() || message->IsTheHole()); |
+ if (HasCaught() && !message->IsTheHole()) { |
return v8::Utils::MessageToLocal(i::Handle<i::Object>(message, isolate_)); |
} else { |
return v8::Local<v8::Message>(); |
@@ -2176,8 +2218,12 @@ v8::Local<v8::Message> v8::TryCatch::Message() const { |
void v8::TryCatch::Reset() { |
ASSERT(isolate_ == i::Isolate::Current()); |
- exception_ = isolate_->heap()->the_hole_value(); |
- message_ = i::Smi::FromInt(0); |
+ i::Object* the_hole = isolate_->heap()->the_hole_value(); |
+ exception_ = the_hole; |
+ message_obj_ = the_hole; |
+ message_script_ = the_hole; |
+ message_start_pos_ = 0; |
+ message_end_pos_ = 0; |
} |
@@ -2916,14 +2962,12 @@ Local<Integer> Value::ToInteger() const { |
} |
-#ifdef V8_ENABLE_CHECKS |
-void i::Internals::CheckInitialized(v8::Isolate* external_isolate) { |
+void i::Internals::CheckInitializedImpl(v8::Isolate* external_isolate) { |
i::Isolate* isolate = reinterpret_cast<i::Isolate*>(external_isolate); |
ApiCheck(isolate != NULL && isolate->IsInitialized() && !i::V8::IsDead(), |
"v8::internal::Internals::CheckInitialized()", |
"Isolate is not initialized or V8 has died"); |
} |
-#endif |
void External::CheckCast(v8::Value* that) { |
@@ -3479,7 +3523,7 @@ bool v8::Object::SetPrototype(Handle<Value> value) { |
// to propagate outside. |
TryCatch try_catch; |
EXCEPTION_PREAMBLE(isolate); |
- i::Handle<i::Object> result = i::SetPrototype(self, value_obj); |
+ i::Handle<i::Object> result = i::JSObject::SetPrototype(self, value_obj); |
has_pending_exception = result.is_null(); |
EXCEPTION_BAILOUT_CHECK(isolate, false); |
return true; |
@@ -4382,6 +4426,7 @@ bool String::IsOneByte() const { |
return str->HasOnlyOneByteChars(); |
} |
+ |
// Helpers for ContainsOnlyOneByteHelper |
template<size_t size> struct OneByteMask; |
template<> struct OneByteMask<4> { |
@@ -4395,6 +4440,8 @@ static const uintptr_t kAlignmentMask = sizeof(uintptr_t) - 1; |
static inline bool Unaligned(const uint16_t* chars) { |
return reinterpret_cast<const uintptr_t>(chars) & kAlignmentMask; |
} |
+ |
+ |
static inline const uint16_t* Align(const uint16_t* chars) { |
return reinterpret_cast<uint16_t*>( |
reinterpret_cast<uintptr_t>(chars) & ~kAlignmentMask); |
@@ -5211,7 +5258,7 @@ bool v8::V8::Initialize() { |
if (isolate != NULL && isolate->IsInitialized()) { |
return true; |
} |
- return InitializeHelper(); |
+ return InitializeHelper(isolate); |
} |
@@ -5227,7 +5274,30 @@ void v8::V8::SetReturnAddressLocationResolver( |
bool v8::V8::SetFunctionEntryHook(FunctionEntryHook entry_hook) { |
- return i::ProfileEntryHookStub::SetFunctionEntryHook(entry_hook); |
+ return SetFunctionEntryHook(Isolate::GetCurrent(), entry_hook); |
+} |
+ |
+ |
+bool v8::V8::SetFunctionEntryHook(Isolate* ext_isolate, |
+ FunctionEntryHook entry_hook) { |
+ ASSERT(ext_isolate != NULL); |
+ ASSERT(entry_hook != NULL); |
+ |
+ i::Isolate* isolate = reinterpret_cast<i::Isolate*>(ext_isolate); |
+ |
+ // The entry hook can only be set before the Isolate is initialized, as |
+ // otherwise the Isolate's code stubs generated at initialization won't |
+ // contain entry hooks. |
+ if (isolate->IsInitialized()) |
+ return false; |
+ |
+ // Setting an entry hook is a one-way operation, once set, it cannot be |
+ // changed or unset. |
+ if (isolate->function_entry_hook() != NULL) |
+ return false; |
+ |
+ isolate->set_function_entry_hook(entry_hook); |
+ return true; |
} |
@@ -6218,6 +6288,7 @@ bool v8::ArrayBuffer::IsExternal() const { |
return Utils::OpenHandle(this)->is_external(); |
} |
+ |
v8::ArrayBuffer::Contents v8::ArrayBuffer::Externalize() { |
i::Handle<i::JSArrayBuffer> obj = Utils::OpenHandle(this); |
ApiCheck(!obj->is_external(), |
@@ -6518,6 +6589,7 @@ v8::AssertNoGCScope::AssertNoGCScope(v8::Isolate* isolate) { |
disallow_heap_allocation_ = new i::DisallowHeapAllocation(); |
} |
+ |
v8::AssertNoGCScope::~AssertNoGCScope() { |
delete static_cast<i::DisallowHeapAllocation*>(disallow_heap_allocation_); |
} |
@@ -6581,6 +6653,7 @@ void V8::SetCounterFunction(CounterLookupCallback callback) { |
isolate->stats_table()->SetCounterFunction(callback); |
} |
+ |
void V8::SetCreateHistogramFunction(CreateHistogramCallback callback) { |
i::Isolate* isolate = EnterIsolateIfNeeded(); |
if (IsDeadCheck(isolate, "v8::V8::SetCreateHistogramFunction()")) return; |
@@ -6589,6 +6662,7 @@ void V8::SetCreateHistogramFunction(CreateHistogramCallback callback) { |
isolate->counters()->ResetHistograms(); |
} |
+ |
void V8::SetAddHistogramSampleFunction(AddHistogramSampleCallback callback) { |
i::Isolate* isolate = EnterIsolateIfNeeded(); |
if (IsDeadCheck(isolate, "v8::V8::SetAddHistogramSampleFunction()")) return; |
@@ -6936,6 +7010,7 @@ String::Value::~Value() { |
i::DeleteArray(str_); |
} |
+ |
Local<Value> Exception::RangeError(v8::Handle<v8::String> raw_message) { |
i::Isolate* isolate = i::Isolate::Current(); |
LOG_API(isolate, "RangeError"); |
@@ -6952,6 +7027,7 @@ Local<Value> Exception::RangeError(v8::Handle<v8::String> raw_message) { |
return Utils::ToLocal(result); |
} |
+ |
Local<Value> Exception::ReferenceError(v8::Handle<v8::String> raw_message) { |
i::Isolate* isolate = i::Isolate::Current(); |
LOG_API(isolate, "ReferenceError"); |
@@ -6969,6 +7045,7 @@ Local<Value> Exception::ReferenceError(v8::Handle<v8::String> raw_message) { |
return Utils::ToLocal(result); |
} |
+ |
Local<Value> Exception::SyntaxError(v8::Handle<v8::String> raw_message) { |
i::Isolate* isolate = i::Isolate::Current(); |
LOG_API(isolate, "SyntaxError"); |
@@ -6985,6 +7062,7 @@ Local<Value> Exception::SyntaxError(v8::Handle<v8::String> raw_message) { |
return Utils::ToLocal(result); |
} |
+ |
Local<Value> Exception::TypeError(v8::Handle<v8::String> raw_message) { |
i::Isolate* isolate = i::Isolate::Current(); |
LOG_API(isolate, "TypeError"); |
@@ -7001,6 +7079,7 @@ Local<Value> Exception::TypeError(v8::Handle<v8::String> raw_message) { |
return Utils::ToLocal(result); |
} |
+ |
Local<Value> Exception::Error(v8::Handle<v8::String> raw_message) { |
i::Isolate* isolate = i::Isolate::Current(); |
LOG_API(isolate, "Error"); |
@@ -7287,6 +7366,15 @@ Handle<String> CpuProfileNode::GetFunctionName() const { |
} |
+int CpuProfileNode::GetScriptId() const { |
+ i::Isolate* isolate = i::Isolate::Current(); |
+ IsDeadCheck(isolate, "v8::CpuProfileNode::GetScriptId"); |
+ const i::ProfileNode* node = reinterpret_cast<const i::ProfileNode*>(this); |
+ const i::CodeEntry* entry = node->entry(); |
+ return entry->script_id(); |
+} |
+ |
+ |
Handle<String> CpuProfileNode::GetScriptResourceName() const { |
i::Isolate* isolate = i::Isolate::Current(); |
IsDeadCheck(isolate, "v8::CpuProfileNode::GetScriptResourceName"); |
@@ -7365,7 +7453,7 @@ void CpuProfile::Delete() { |
i::CpuProfiler* profiler = isolate->cpu_profiler(); |
ASSERT(profiler != NULL); |
profiler->DeleteProfile(reinterpret_cast<i::CpuProfile*>(this)); |
- if (profiler->GetProfilesCount() == 0 && !profiler->HasDetachedProfiles()) { |
+ if (profiler->GetProfilesCount() == 0) { |
// If this was the last profile, clean up all accessory data as well. |
profiler->DeleteAllProfiles(); |
} |
@@ -7412,27 +7500,9 @@ int CpuProfiler::GetProfileCount() { |
} |
-const CpuProfile* CpuProfiler::GetCpuProfile(int index, |
- Handle<Value> security_token) { |
- return reinterpret_cast<const CpuProfile*>( |
- reinterpret_cast<i::CpuProfiler*>(this)->GetProfile( |
- security_token.IsEmpty() ? NULL : *Utils::OpenHandle(*security_token), |
- index)); |
-} |
- |
- |
const CpuProfile* CpuProfiler::GetCpuProfile(int index) { |
return reinterpret_cast<const CpuProfile*>( |
- reinterpret_cast<i::CpuProfiler*>(this)->GetProfile(NULL, index)); |
-} |
- |
- |
-const CpuProfile* CpuProfiler::FindCpuProfile(unsigned uid, |
- Handle<Value> security_token) { |
- return reinterpret_cast<const CpuProfile*>( |
- reinterpret_cast<i::CpuProfiler*>(this)->FindProfile( |
- security_token.IsEmpty() ? NULL : *Utils::OpenHandle(*security_token), |
- uid)); |
+ reinterpret_cast<i::CpuProfiler*>(this)->GetProfile(index)); |
} |
@@ -7442,19 +7512,9 @@ void CpuProfiler::StartCpuProfiling(Handle<String> title, bool record_samples) { |
} |
-const CpuProfile* CpuProfiler::StopCpuProfiling(Handle<String> title, |
- Handle<Value> security_token) { |
- return reinterpret_cast<const CpuProfile*>( |
- reinterpret_cast<i::CpuProfiler*>(this)->StopProfiling( |
- security_token.IsEmpty() ? NULL : *Utils::OpenHandle(*security_token), |
- *Utils::OpenHandle(*title))); |
-} |
- |
- |
const CpuProfile* CpuProfiler::StopCpuProfiling(Handle<String> title) { |
return reinterpret_cast<const CpuProfile*>( |
reinterpret_cast<i::CpuProfiler*>(this)->StopProfiling( |
- NULL, |
*Utils::OpenHandle(*title))); |
} |
@@ -7673,12 +7733,6 @@ const HeapSnapshot* HeapProfiler::GetHeapSnapshot(int index) { |
} |
-const HeapSnapshot* HeapProfiler::FindHeapSnapshot(unsigned uid) { |
- return reinterpret_cast<const HeapSnapshot*>( |
- reinterpret_cast<i::HeapProfiler*>(this)->FindSnapshot(uid)); |
-} |
- |
- |
SnapshotObjectId HeapProfiler::GetObjectId(Handle<Value> value) { |
i::Handle<i::Object> obj = Utils::OpenHandle(*value); |
return reinterpret_cast<i::HeapProfiler*>(this)->GetSnapshotObjectId(obj); |
@@ -7742,6 +7796,7 @@ void Testing::SetStressRunType(Testing::StressType type) { |
internal::Testing::set_stress_type(type); |
} |
+ |
int Testing::GetStressRuns() { |
if (internal::FLAG_stress_runs != 0) return internal::FLAG_stress_runs; |
#ifdef DEBUG |