diff options
Diffstat (limited to 'src/3rdparty/v8/src/api.cc')
-rw-r--r-- | src/3rdparty/v8/src/api.cc | 515 |
1 files changed, 381 insertions, 134 deletions
diff --git a/src/3rdparty/v8/src/api.cc b/src/3rdparty/v8/src/api.cc index 70d0a8a..cbb3a04 100644 --- a/src/3rdparty/v8/src/api.cc +++ b/src/3rdparty/v8/src/api.cc @@ -33,6 +33,7 @@ #include "../include/v8-profiler.h" #include "../include/v8-testing.h" #include "bootstrapper.h" +#include "code-stubs.h" #include "compiler.h" #include "conversions-inl.h" #include "counters.h" @@ -540,7 +541,9 @@ Extension::Extension(const char* name, source_(source, source_length_), dep_count_(dep_count), deps_(deps), - auto_enable_(false) { } + auto_enable_(false) { + CHECK(source != NULL || source_length_ == 0); +} v8::Handle<Primitive> Undefined() { @@ -640,11 +643,48 @@ void V8::ClearWeak(i::Object** obj) { void V8::MarkIndependent(i::Object** object) { i::Isolate* isolate = i::Isolate::Current(); - LOG_API(isolate, "MakeIndependent"); + LOG_API(isolate, "MarkIndependent"); isolate->global_handles()->MarkIndependent(object); } +void V8::MarkIndependent(i::Isolate* isolate, i::Object** object) { + ASSERT(isolate == i::Isolate::Current()); + LOG_API(isolate, "MarkIndependent"); + isolate->global_handles()->MarkIndependent(object); +} + + +void V8::MarkPartiallyDependent(i::Object** object) { + i::Isolate* isolate = i::Isolate::Current(); + LOG_API(isolate, "MarkPartiallyDependent"); + isolate->global_handles()->MarkPartiallyDependent(object); +} + + +void V8::MarkPartiallyDependent(i::Isolate* isolate, i::Object** object) { + ASSERT(isolate == i::Isolate::Current()); + LOG_API(isolate, "MarkPartiallyDependent"); + isolate->global_handles()->MarkPartiallyDependent(object); +} + + +bool V8::IsGlobalIndependent(i::Object** obj) { + i::Isolate* isolate = i::Isolate::Current(); + LOG_API(isolate, "IsGlobalIndependent"); + if (!isolate->IsInitialized()) return false; + return i::GlobalHandles::IsIndependent(obj); +} + + +bool V8::IsGlobalIndependent(i::Isolate* isolate, i::Object** obj) { + ASSERT(isolate == i::Isolate::Current()); + LOG_API(isolate, "IsGlobalIndependent"); + if (!isolate->IsInitialized()) return false; + return i::GlobalHandles::IsIndependent(obj); +} + + bool V8::IsGlobalNearDeath(i::Object** obj) { i::Isolate* isolate = i::Isolate::Current(); LOG_API(isolate, "IsGlobalNearDeath"); @@ -668,6 +708,14 @@ void V8::DisposeGlobal(i::Object** obj) { isolate->global_handles()->Destroy(obj); } + +void V8::DisposeGlobal(i::Isolate* isolate, i::Object** obj) { + ASSERT(isolate == i::Isolate::Current()); + LOG_API(isolate, "DisposeGlobal"); + if (!isolate->IsInitialized()) return; + isolate->global_handles()->Destroy(obj); +} + // --- H a n d l e s --- @@ -762,13 +810,13 @@ void Context::Exit() { } -void Context::SetData(v8::Handle<String> data) { +void Context::SetData(v8::Handle<Value> data) { i::Handle<i::Context> env = Utils::OpenHandle(this); i::Isolate* isolate = env->GetIsolate(); if (IsDeadCheck(isolate, "v8::Context::SetData()")) return; i::Handle<i::Object> raw_data = Utils::OpenHandle(*data); - ASSERT(env->IsGlobalContext()); - if (env->IsGlobalContext()) { + ASSERT(env->IsNativeContext()); + if (env->IsNativeContext()) { env->set_data(*raw_data); } } @@ -778,16 +826,13 @@ v8::Local<v8::Value> Context::GetData() { i::Handle<i::Context> env = Utils::OpenHandle(this); i::Isolate* isolate = env->GetIsolate(); if (IsDeadCheck(isolate, "v8::Context::GetData()")) { - return v8::Local<Value>(); + return Local<Value>(); } - i::Object* raw_result = NULL; - ASSERT(env->IsGlobalContext()); - if (env->IsGlobalContext()) { - raw_result = env->data(); - } else { + ASSERT(env->IsNativeContext()); + if (!env->IsNativeContext()) { return Local<Value>(); } - i::Handle<i::Object> result(raw_result, isolate); + i::Handle<i::Object> result(env->data(), isolate); return Utils::ToLocal(result); } @@ -990,6 +1035,12 @@ Local<Signature> Signature::New(Handle<FunctionTemplate> receiver, } +Local<AccessorSignature> AccessorSignature::New( + Handle<FunctionTemplate> receiver) { + return Utils::AccessorSignatureToLocal(Utils::OpenHandle(*receiver)); +} + + Local<TypeSwitch> TypeSwitch::New(Handle<FunctionTemplate> type) { Handle<FunctionTemplate> types[1] = { type }; return TypeSwitch::New(1, types); @@ -1057,9 +1108,9 @@ static i::Handle<i::AccessorInfo> MakeAccessorInfo( AccessorSetter setter, v8::Handle<Value> data, v8::AccessControl settings, - v8::PropertyAttribute attributes) { + v8::PropertyAttribute attributes, + v8::Handle<AccessorSignature> signature) { i::Handle<i::AccessorInfo> obj = FACTORY->NewAccessorInfo(); - ASSERT(getter != NULL); SET_FIELD_WRAPPED(obj, set_getter, getter); SET_FIELD_WRAPPED(obj, set_setter, setter); if (data.IsEmpty()) data = v8::Undefined(); @@ -1069,6 +1120,9 @@ static i::Handle<i::AccessorInfo> MakeAccessorInfo( if (settings & ALL_CAN_WRITE) obj->set_all_can_write(true); if (settings & PROHIBITS_OVERWRITING) obj->set_prohibits_overwriting(true); obj->set_property_attributes(static_cast<PropertyAttributes>(attributes)); + if (!signature.IsEmpty()) { + obj->set_expected_receiver_type(*Utils::OpenHandle(*signature)); + } return obj; } @@ -1079,7 +1133,8 @@ void FunctionTemplate::AddInstancePropertyAccessor( AccessorSetter setter, v8::Handle<Value> data, v8::AccessControl settings, - v8::PropertyAttribute attributes) { + v8::PropertyAttribute attributes, + v8::Handle<AccessorSignature> signature) { i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); if (IsDeadCheck(isolate, "v8::FunctionTemplate::AddInstancePropertyAccessor()")) { @@ -1088,9 +1143,9 @@ void FunctionTemplate::AddInstancePropertyAccessor( ENTER_V8(isolate); i::HandleScope scope(isolate); - i::Handle<i::AccessorInfo> obj = MakeAccessorInfo(name, - getter, setter, data, - settings, attributes); + i::Handle<i::AccessorInfo> obj = MakeAccessorInfo(name, getter, setter, data, + settings, attributes, + signature); i::Handle<i::Object> list(Utils::OpenHandle(this)->property_accessors()); if (list->IsUndefined()) { list = NeanderArray().value(); @@ -1277,7 +1332,8 @@ void ObjectTemplate::SetAccessor(v8::Handle<String> name, AccessorSetter setter, v8::Handle<Value> data, AccessControl settings, - PropertyAttribute attribute) { + PropertyAttribute attribute, + v8::Handle<AccessorSignature> signature) { i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); if (IsDeadCheck(isolate, "v8::ObjectTemplate::SetAccessor()")) return; ENTER_V8(isolate); @@ -1291,7 +1347,8 @@ void ObjectTemplate::SetAccessor(v8::Handle<String> name, setter, data, settings, - attribute); + attribute, + signature); } @@ -1593,9 +1650,10 @@ Local<Script> Script::New(v8::Handle<String> source, name_obj, line_offset, column_offset, + isolate->global_context(), NULL, pre_data_impl, - Utils::OpenHandle(*script_data), + Utils::OpenHandle(*script_data, true), i::NOT_NATIVES_CODE, compile_flags); has_pending_exception = result.is_null(); @@ -1670,7 +1728,7 @@ Local<Value> Script::Run(Handle<Object> qml) { fun = i::Handle<i::JSFunction>(i::JSFunction::cast(*obj), isolate); } EXCEPTION_PREAMBLE(isolate); - i::Handle<i::Object> qmlglobal = Utils::OpenHandle(*qml); + i::Handle<i::Object> qmlglobal = Utils::OpenHandle(*qml, true); i::Handle<i::Object> receiver( isolate->context()->global_proxy(), isolate); i::Handle<i::Object> result = @@ -3102,6 +3160,17 @@ Local<String> v8::Object::ObjectProtoToString() { } +Local<Value> v8::Object::GetConstructor() { + i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); + ON_BAILOUT(isolate, "v8::Object::GetConstructor()", + return Local<v8::Function>()); + ENTER_V8(isolate); + i::Handle<i::JSObject> self = Utils::OpenHandle(this); + i::Handle<i::Object> constructor(self->GetConstructor()); + return Utils::ToLocal(constructor); +} + + Local<String> v8::Object::GetConstructorName() { i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); ON_BAILOUT(isolate, "v8::Object::GetConstructorName()", @@ -3163,9 +3232,10 @@ bool Object::SetAccessor(Handle<String> name, ON_BAILOUT(isolate, "v8::Object::SetAccessor()", return false); ENTER_V8(isolate); i::HandleScope scope(isolate); - i::Handle<i::AccessorInfo> info = MakeAccessorInfo(name, - getter, setter, data, - settings, attributes); + v8::Handle<AccessorSignature> signature; + i::Handle<i::AccessorInfo> info = MakeAccessorInfo(name, getter, setter, data, + settings, attributes, + signature); bool fast = Utils::OpenHandle(this)->HasFastProperties(); i::Handle<i::Object> result = i::SetAccessor(Utils::OpenHandle(this), info); if (result.is_null() || result->IsUndefined()) return false; @@ -3293,7 +3363,7 @@ void v8::Object::TurnOnAccessCheck() { i::Deoptimizer::DeoptimizeGlobalObject(*obj); i::Handle<i::Map> new_map = - isolate->factory()->CopyMapDropTransitions(i::Handle<i::Map>(obj->map())); + isolate->factory()->CopyMap(i::Handle<i::Map>(obj->map())); new_map->set_is_access_check_needed(true); obj->set_map(*new_map); } @@ -3328,7 +3398,7 @@ static i::Context* GetCreationContext(i::JSObject* object) { } else { function = i::JSFunction::cast(constructor); } - return function->context()->global_context(); + return function->context()->native_context(); } @@ -3357,13 +3427,15 @@ bool v8::Object::SetHiddenValue(v8::Handle<v8::String> key, v8::Handle<v8::Value> value) { i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); ON_BAILOUT(isolate, "v8::Object::SetHiddenValue()", return false); + if (value.IsEmpty()) return DeleteHiddenValue(key); ENTER_V8(isolate); i::HandleScope scope(isolate); i::Handle<i::JSObject> self = Utils::OpenHandle(this); i::Handle<i::String> key_obj = Utils::OpenHandle(*key); + i::Handle<i::String> key_symbol = FACTORY->LookupSymbol(key_obj); i::Handle<i::Object> value_obj = Utils::OpenHandle(*value); i::Handle<i::Object> result = - i::JSObject::SetHiddenProperty(self, key_obj, value_obj); + i::JSObject::SetHiddenProperty(self, key_symbol, value_obj); return *result == *self; } @@ -3375,7 +3447,8 @@ v8::Local<v8::Value> v8::Object::GetHiddenValue(v8::Handle<v8::String> key) { ENTER_V8(isolate); i::Handle<i::JSObject> self = Utils::OpenHandle(this); i::Handle<i::String> key_obj = Utils::OpenHandle(*key); - i::Handle<i::Object> result(self->GetHiddenProperty(*key_obj)); + i::Handle<i::String> key_symbol = FACTORY->LookupSymbol(key_obj); + i::Handle<i::Object> result(self->GetHiddenProperty(*key_symbol)); if (result->IsUndefined()) return v8::Local<v8::Value>(); return Utils::ToLocal(result); } @@ -3388,7 +3461,8 @@ bool v8::Object::DeleteHiddenValue(v8::Handle<v8::String> key) { i::HandleScope scope(isolate); i::Handle<i::JSObject> self = Utils::OpenHandle(this); i::Handle<i::String> key_obj = Utils::OpenHandle(*key); - self->DeleteHiddenProperty(*key_obj); + i::Handle<i::String> key_symbol = FACTORY->LookupSymbol(key_obj); + self->DeleteHiddenProperty(*key_symbol); return true; } @@ -3456,7 +3530,7 @@ void v8::Object::SetIndexedPropertiesToPixelData(uint8_t* data, int length) { ON_BAILOUT(isolate, "v8::SetElementsToPixelData()", return); ENTER_V8(isolate); i::HandleScope scope(isolate); - if (!ApiCheck(length <= i::ExternalPixelArray::kMaxLength, + if (!ApiCheck(length >= 0 && length <= i::ExternalPixelArray::kMaxLength, "v8::Object::SetIndexedPropertiesToPixelData()", "length exceeds max acceptable value")) { return; @@ -3512,7 +3586,7 @@ void v8::Object::SetIndexedPropertiesToExternalArrayData( ON_BAILOUT(isolate, "v8::SetIndexedPropertiesToExternalArrayData()", return); ENTER_V8(isolate); i::HandleScope scope(isolate); - if (!ApiCheck(length <= i::ExternalArray::kMaxLength, + if (!ApiCheck(length >= 0 && length <= i::ExternalArray::kMaxLength, "v8::Object::SetIndexedPropertiesToExternalArrayData()", "length exceeds max acceptable value")) { return; @@ -3745,8 +3819,9 @@ ScriptOrigin Function::GetScriptOrigin() const { i::Handle<i::JSFunction> func = Utils::OpenHandle(this); if (func->shared()->script()->IsScript()) { i::Handle<i::Script> script(i::Script::cast(func->shared()->script())); + i::Handle<i::Object> scriptName = GetScriptNameOrSourceURL(script); v8::ScriptOrigin origin( - Utils::ToLocal(i::Handle<i::Object>(script->name())), + Utils::ToLocal(scriptName), v8::Integer::New(script->line_offset()->value()), v8::Integer::New(script->column_offset()->value())); return origin; @@ -3929,26 +4004,6 @@ uint32_t String::ComputeHash(char *string, int length) { } -uint16_t String::GetCharacter(int index) { - i::Handle<i::String> str = Utils::OpenHandle(this); - return str->Get(index); -} - - -bool String::Equals(uint16_t *string, int length) { - i::Handle<i::String> str = Utils::OpenHandle(this); - if (IsDeadCheck(str->GetIsolate(), "v8::String::Equals()")) return 0; - return str->SlowEqualsExternal(string, length); -} - - -bool String::Equals(char *string, int length) { - i::Handle<i::String> str = Utils::OpenHandle(this); - if (IsDeadCheck(str->GetIsolate(), "v8::String::Equals()")) return 0; - return str->SlowEqualsExternal(string, length); -} - - int String::WriteUtf8(char* buffer, int capacity, int* nchars_ref, @@ -3958,6 +4013,9 @@ int String::WriteUtf8(char* buffer, LOG_API(isolate, "String::WriteUtf8"); ENTER_V8(isolate); i::Handle<i::String> str = Utils::OpenHandle(this); + if (options & HINT_MANY_WRITES_EXPECTED) { + FlattenString(str); // Flatten the string for efficiency. + } int string_length = str->length(); if (str->IsAsciiRepresentation()) { int len; @@ -4014,11 +4072,7 @@ int String::WriteUtf8(char* buffer, // Slow case. i::StringInputBuffer& write_input_buffer = *isolate->write_input_buffer(); isolate->string_tracker()->RecordWrite(str); - if (options & HINT_MANY_WRITES_EXPECTED) { - // Flatten the string for efficiency. This applies whether we are - // using StringInputBuffer or Get(i) to access the characters. - FlattenString(str); - } + write_input_buffer.Reset(0, *str); int len = str->length(); // Encode the first K - 3 bytes directly into the buffer since we @@ -4060,8 +4114,9 @@ int String::WriteUtf8(char* buffer, c, unibrow::Utf16::kNoPreviousCharacter); if (pos + written <= capacity) { - for (int j = 0; j < written; j++) + for (int j = 0; j < written; j++) { buffer[pos + j] = intermediate[j]; + } pos += written; nchars++; } else { @@ -4074,8 +4129,9 @@ int String::WriteUtf8(char* buffer, } if (nchars_ref != NULL) *nchars_ref = nchars; if (!(options & NO_NULL_TERMINATION) && - (i == len && (capacity == -1 || pos < capacity))) + (i == len && (capacity == -1 || pos < capacity))) { buffer[pos++] = '\0'; + } return pos; } @@ -4088,28 +4144,45 @@ int String::WriteAscii(char* buffer, if (IsDeadCheck(isolate, "v8::String::WriteAscii()")) return 0; LOG_API(isolate, "String::WriteAscii"); ENTER_V8(isolate); - i::StringInputBuffer& write_input_buffer = *isolate->write_input_buffer(); ASSERT(start >= 0 && length >= -1); i::Handle<i::String> str = Utils::OpenHandle(this); isolate->string_tracker()->RecordWrite(str); if (options & HINT_MANY_WRITES_EXPECTED) { - // Flatten the string for efficiency. This applies whether we are - // using StringInputBuffer or Get(i) to access the characters. - str->TryFlatten(); + FlattenString(str); // Flatten the string for efficiency. } + + if (str->IsAsciiRepresentation()) { + // WriteToFlat is faster than using the StringInputBuffer. + if (length == -1) length = str->length() + 1; + int len = i::Min(length, str->length() - start); + i::String::WriteToFlat(*str, buffer, start, start + len); + if (!(options & PRESERVE_ASCII_NULL)) { + for (int i = 0; i < len; i++) { + if (buffer[i] == '\0') buffer[i] = ' '; + } + } + if (!(options & NO_NULL_TERMINATION) && length > len) { + buffer[len] = '\0'; + } + return len; + } + + i::StringInputBuffer& write_input_buffer = *isolate->write_input_buffer(); int end = length; - if ( (length == -1) || (length > str->length() - start) ) + if ((length == -1) || (length > str->length() - start)) { end = str->length() - start; + } if (end < 0) return 0; write_input_buffer.Reset(start, *str); int i; for (i = 0; i < end; i++) { char c = static_cast<char>(write_input_buffer.GetNext()); - if (c == '\0') c = ' '; + if (c == '\0' && !(options & PRESERVE_ASCII_NULL)) c = ' '; buffer[i] = c; } - if (!(options & NO_NULL_TERMINATION) && (length == -1 || i < length)) + if (!(options & NO_NULL_TERMINATION) && (length == -1 || i < length)) { buffer[i] = '\0'; + } return i; } @@ -4128,7 +4201,7 @@ int String::Write(uint16_t* buffer, if (options & HINT_MANY_WRITES_EXPECTED) { // Flatten the string for efficiency. This applies whether we are // using StringInputBuffer or Get(i) to access the characters. - str->TryFlatten(); + FlattenString(str); } int end = start + length; if ((length == -1) || (length > str->length() - start) ) @@ -4176,6 +4249,29 @@ void v8::String::VerifyExternalStringResource( CHECK_EQ(expected, value); } +void v8::String::VerifyExternalStringResourceBase( + v8::String::ExternalStringResourceBase* value, Encoding encoding) const { + i::Handle<i::String> str = Utils::OpenHandle(this); + const v8::String::ExternalStringResourceBase* expected; + Encoding expectedEncoding; + if (i::StringShape(*str).IsExternalAscii()) { + const void* resource = + i::Handle<i::ExternalAsciiString>::cast(str)->resource(); + expected = reinterpret_cast<const ExternalStringResourceBase*>(resource); + expectedEncoding = ASCII_ENCODING; + } else if (i::StringShape(*str).IsExternalTwoByte()) { + const void* resource = + i::Handle<i::ExternalTwoByteString>::cast(str)->resource(); + expected = reinterpret_cast<const ExternalStringResourceBase*>(resource); + expectedEncoding = TWO_BYTE_ENCODING; + } else { + expected = NULL; + expectedEncoding = str->IsAsciiRepresentation() ? ASCII_ENCODING + : TWO_BYTE_ENCODING; + } + CHECK_EQ(expected, value); + CHECK_EQ(expectedEncoding, encoding); +} const v8::String::ExternalAsciiStringResource* v8::String::GetExternalAsciiStringResource() const { @@ -4314,8 +4410,9 @@ void v8::Object::SetPointerInInternalField(int index, void* value) { i::Handle<i::Foreign> foreign = isolate->factory()->NewForeign( reinterpret_cast<i::Address>(value), i::TENURED); - if (!foreign.is_null()) - Utils::OpenHandle(this)->SetInternalField(index, *foreign); + if (!foreign.is_null()) { + Utils::OpenHandle(this)->SetInternalField(index, *foreign); + } } ASSERT_EQ(value, GetPointerFromInternalField(index)); } @@ -4372,6 +4469,20 @@ void v8::V8::SetReturnAddressLocationResolver( } +bool v8::V8::SetFunctionEntryHook(FunctionEntryHook entry_hook) { + return i::ProfileEntryHookStub::SetFunctionEntryHook(entry_hook); +} + + +void v8::V8::SetJitCodeEventHandler( + JitCodeEventOptions options, JitCodeEventHandler event_handler) { + i::Isolate* isolate = i::Isolate::Current(); + // Ensure that logging is initialized for our isolate. + isolate->InitializeLoggingAndCounters(); + isolate->logger()->SetCodeEventHandler(options, event_handler); +} + + bool v8::V8::Dispose() { i::Isolate* isolate = i::Isolate::Current(); if (!ApiCheck(isolate != NULL && isolate->IsDefaultIsolate(), @@ -4386,6 +4497,7 @@ bool v8::V8::Dispose() { HeapStatistics::HeapStatistics(): total_heap_size_(0), total_heap_size_executable_(0), + total_physical_size_(0), used_heap_size_(0), heap_size_limit_(0) { } @@ -4395,6 +4507,7 @@ void v8::V8::GetHeapStatistics(HeapStatistics* heap_statistics) { // Isolate is unitialized thus heap is not configured yet. heap_statistics->set_total_heap_size(0); heap_statistics->set_total_heap_size_executable(0); + heap_statistics->set_total_physical_size(0); heap_statistics->set_used_heap_size(0); heap_statistics->set_heap_size_limit(0); return; @@ -4404,6 +4517,7 @@ void v8::V8::GetHeapStatistics(HeapStatistics* heap_statistics) { heap_statistics->set_total_heap_size(heap->CommittedMemory()); heap_statistics->set_total_heap_size_executable( heap->CommittedMemoryExecutable()); + heap_statistics->set_total_physical_size(heap->CommittedPhysicalMemory()); heap_statistics->set_used_heap_size(heap->SizeOfObjects()); heap_statistics->set_heap_size_limit(heap->MaxReserved()); } @@ -4416,6 +4530,30 @@ void v8::V8::VisitExternalResources(ExternalResourceVisitor* visitor) { } +void v8::V8::VisitHandlesWithClassIds(PersistentHandleVisitor* visitor) { + i::Isolate* isolate = i::Isolate::Current(); + IsDeadCheck(isolate, "v8::V8::VisitHandlesWithClassId"); + + i::AssertNoAllocation no_allocation; + + class VisitorAdapter : public i::ObjectVisitor { + public: + explicit VisitorAdapter(PersistentHandleVisitor* visitor) + : visitor_(visitor) {} + virtual void VisitPointers(i::Object** start, i::Object** end) { + UNREACHABLE(); + } + virtual void VisitEmbedderReference(i::Object** p, uint16_t class_id) { + visitor_->VisitPersistentHandle(ToApi<Value>(i::Handle<i::Object>(p)), + class_id); + } + private: + PersistentHandleVisitor* visitor_; + } visitor_adapter(visitor); + isolate->global_handles()->IterateAllRootsWithClassIds(&visitor_adapter); +} + + bool v8::V8::IdleNotification(int hint) { // Returning true tells the caller that it need not // continue to call IdleNotification. @@ -4506,7 +4644,7 @@ Persistent<Context> v8::Context::New( // Create the environment. env = isolate->bootstrapper()->CreateEnvironment( isolate, - Utils::OpenHandle(*global_object), + Utils::OpenHandle(*global_object, true), proxy_template, extensions); @@ -4550,7 +4688,7 @@ void v8::Context::UseDefaultSecurityToken() { } ENTER_V8(isolate); i::Handle<i::Context> env = Utils::OpenHandle(this); - env->set_security_token(env->global()); + env->set_security_token(env->global_object()); } @@ -4595,7 +4733,7 @@ v8::Local<v8::Context> Context::GetCurrent() { if (IsDeadCheck(isolate, "v8::Context::GetCurrent()")) { return Local<Context>(); } - i::Handle<i::Object> current = isolate->global_context(); + i::Handle<i::Object> current = isolate->native_context(); if (current.is_null()) return Local<Context>(); i::Handle<i::Context> context = i::Handle<i::Context>::cast(current); return Utils::ToLocal(context); @@ -4608,7 +4746,7 @@ v8::Local<v8::Context> Context::GetCalling() { return Local<Context>(); } i::Handle<i::Object> calling = - isolate->GetCallingGlobalContext(); + isolate->GetCallingNativeContext(); if (calling.is_null()) return Local<Context>(); i::Handle<i::Context> context = i::Handle<i::Context>::cast(calling); return Utils::ToLocal(context); @@ -4625,8 +4763,8 @@ v8::Local<v8::Object> Context::GetCallingQmlGlobal() { i::JavaScriptFrameIterator it; if (it.done()) return Local<Object>(); context = i::Context::cast(it.frame()->context()); - if (!context->qml_global()->IsUndefined()) { - i::Handle<i::Object> qmlglobal(context->qml_global()); + if (!context->qml_global_object()->IsUndefined()) { + i::Handle<i::Object> qmlglobal(context->qml_global_object()); return Utils::ToLocal(i::Handle<i::JSObject>::cast(qmlglobal)); } else { return Local<Object>(); @@ -4676,9 +4814,9 @@ void Context::ReattachGlobal(Handle<Object> global_object) { i::Object** ctx = reinterpret_cast<i::Object**>(this); i::Handle<i::Context> context = i::Handle<i::Context>::cast(i::Handle<i::Object>(ctx)); - isolate->bootstrapper()->ReattachGlobal( - context, - Utils::OpenHandle(*global_object)); + i::Handle<i::JSGlobalProxy> global_proxy = + i::Handle<i::JSGlobalProxy>::cast(Utils::OpenHandle(*global_object)); + isolate->bootstrapper()->ReattachGlobal(context, global_proxy); } @@ -4710,11 +4848,32 @@ bool Context::IsCodeGenerationFromStringsAllowed() { } +void Context::SetErrorMessageForCodeGenerationFromStrings( + Handle<String> error) { + i::Isolate* isolate = i::Isolate::Current(); + if (IsDeadCheck(isolate, + "v8::Context::SetErrorMessageForCodeGenerationFromStrings()")) { + return; + } + ENTER_V8(isolate); + i::Object** ctx = reinterpret_cast<i::Object**>(this); + i::Handle<i::Context> context = + i::Handle<i::Context>::cast(i::Handle<i::Object>(ctx)); + i::Handle<i::Object> error_handle = Utils::OpenHandle(*error); + context->set_error_message_for_code_gen_from_strings(*error_handle); +} + + void V8::SetWrapperClassId(i::Object** global_handle, uint16_t class_id) { i::GlobalHandles::SetWrapperClassId(global_handle, class_id); } +uint16_t V8::GetWrapperClassId(internal::Object** global_handle) { + return i::GlobalHandles::GetWrapperClassId(global_handle); +} + + Local<v8::Object> ObjectTemplate::NewInstance() { i::Isolate* isolate = i::Isolate::Current(); ON_BAILOUT(isolate, "v8::ObjectTemplate::NewInstance()", @@ -4932,6 +5091,7 @@ Local<String> v8::String::NewExternal( EnsureInitializedForIsolate(isolate, "v8::String::NewExternal()"); LOG_API(isolate, "String::NewExternal"); ENTER_V8(isolate); + CHECK(resource && resource->data()); i::Handle<i::String> result = NewExternalStringHandle(isolate, resource); isolate->heap()->external_string_table()->AddString(*result); return Utils::ToLocal(result); @@ -4952,6 +5112,7 @@ bool v8::String::MakeExternal(v8::String::ExternalStringResource* resource) { if (isolate->heap()->IsInGCPostProcessing()) { return false; } + CHECK(resource && resource->data()); bool result = obj->MakeExternal(resource); if (result && !obj->IsSymbol()) { isolate->heap()->external_string_table()->AddString(*obj); @@ -4966,6 +5127,7 @@ Local<String> v8::String::NewExternal( EnsureInitializedForIsolate(isolate, "v8::String::NewExternal()"); LOG_API(isolate, "String::NewExternal"); ENTER_V8(isolate); + CHECK(resource && resource->data()); i::Handle<i::String> result = NewExternalAsciiStringHandle(isolate, resource); isolate->heap()->external_string_table()->AddString(*result); return Utils::ToLocal(result); @@ -4987,6 +5149,7 @@ bool v8::String::MakeExternal( if (isolate->heap()->IsInGCPostProcessing()) { return false; } + CHECK(resource && resource->data()); bool result = obj->MakeExternal(resource); if (result && !obj->IsSymbol()) { isolate->heap()->external_string_table()->AddString(*obj); @@ -5236,7 +5399,7 @@ Local<Object> Array::CloneElementAt(uint32_t index) { i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); ON_BAILOUT(isolate, "v8::Array::CloneElementAt()", return Local<Object>()); i::Handle<i::JSObject> self = Utils::OpenHandle(this); - if (!self->HasFastElements()) { + if (!self->HasFastObjectElements()) { return Local<Object>(); } i::FixedArray* elms = i::FixedArray::cast(self->elements()); @@ -5282,24 +5445,39 @@ Local<Number> v8::Number::New(double value) { Local<Integer> v8::Integer::New(int32_t value) { i::Isolate* isolate = i::Isolate::UncheckedCurrent(); EnsureInitializedForIsolate(isolate, "v8::Integer::New()"); + return v8::Integer::New(value, reinterpret_cast<Isolate*>(isolate)); +} + + +Local<Integer> Integer::NewFromUnsigned(uint32_t value) { + i::Isolate* isolate = i::Isolate::Current(); + EnsureInitializedForIsolate(isolate, "v8::Integer::NewFromUnsigned()"); + return Integer::NewFromUnsigned(value, reinterpret_cast<Isolate*>(isolate)); +} + + +Local<Integer> v8::Integer::New(int32_t value, Isolate* isolate) { + i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate); + ASSERT(internal_isolate->IsInitialized()); if (i::Smi::IsValid(value)) { return Utils::IntegerToLocal(i::Handle<i::Object>(i::Smi::FromInt(value), - isolate)); + internal_isolate)); } - ENTER_V8(isolate); - i::Handle<i::Object> result = isolate->factory()->NewNumber(value); + ENTER_V8(internal_isolate); + i::Handle<i::Object> result = internal_isolate->factory()->NewNumber(value); return Utils::IntegerToLocal(result); } -Local<Integer> Integer::NewFromUnsigned(uint32_t value) { +Local<Integer> v8::Integer::NewFromUnsigned(uint32_t value, Isolate* isolate) { + i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate); + ASSERT(internal_isolate->IsInitialized()); bool fits_into_int32_t = (value & (1 << 31)) == 0; if (fits_into_int32_t) { - return Integer::New(static_cast<int32_t>(value)); + return Integer::New(static_cast<int32_t>(value), isolate); } - i::Isolate* isolate = i::Isolate::Current(); - ENTER_V8(isolate); - i::Handle<i::Object> result = isolate->factory()->NewNumber(value); + ENTER_V8(internal_isolate); + i::Handle<i::Object> result = internal_isolate->factory()->NewNumber(value); return Utils::IntegerToLocal(result); } @@ -5309,19 +5487,14 @@ void V8::IgnoreOutOfMemoryException() { } -bool V8::AddMessageListener(MessageCallback that, Handle<Value> data) { +bool V8::AddMessageListener(MessageCallback that) { i::Isolate* isolate = i::Isolate::Current(); EnsureInitializedForIsolate(isolate, "v8::V8::AddMessageListener()"); ON_BAILOUT(isolate, "v8::V8::AddMessageListener()", return false); ENTER_V8(isolate); i::HandleScope scope(isolate); NeanderArray listeners(isolate->factory()->message_listeners()); - NeanderObject obj(2); - obj.set(0, *isolate->factory()->NewForeign(FUNCTION_ADDR(that))); - obj.set(1, data.IsEmpty() ? - isolate->heap()->undefined_value() : - *Utils::OpenHandle(*data)); - listeners.add(obj.value()); + listeners.add(isolate->factory()->NewForeign(FUNCTION_ADDR(that))); return true; } @@ -5336,8 +5509,7 @@ void V8::RemoveMessageListeners(MessageCallback that) { for (int i = 0; i < listeners.length(); i++) { if (listeners.get(i)->IsUndefined()) continue; // skip deleted ones - NeanderObject listener(i::JSObject::cast(listeners.get(i))); - i::Handle<i::Foreign> callback_obj(i::Foreign::cast(listener.get(0))); + i::Handle<i::Foreign> callback_obj(i::Foreign::cast(listeners.get(i))); if (callback_obj->foreign_address() == FUNCTION_ADDR(that)) { listeners.set(i, isolate->heap()->undefined_value()); } @@ -5366,6 +5538,8 @@ void V8::SetCreateHistogramFunction(CreateHistogramCallback callback) { i::Isolate* isolate = EnterIsolateIfNeeded(); if (IsDeadCheck(isolate, "v8::V8::SetCreateHistogramFunction()")) return; isolate->stats_table()->SetCreateHistogramFunction(callback); + isolate->InitializeLoggingAndCounters(); + isolate->counters()->ResetHistograms(); } void V8::SetAddHistogramSampleFunction(AddHistogramSampleCallback callback) { @@ -5426,8 +5600,9 @@ void V8::AddImplicitReferences(Persistent<Object> parent, intptr_t V8::AdjustAmountOfExternalAllocatedMemory(intptr_t change_in_bytes) { - i::Isolate* isolate = i::Isolate::Current(); - if (IsDeadCheck(isolate, "v8::V8::AdjustAmountOfExternalAllocatedMemory()")) { + i::Isolate* isolate = i::Isolate::UncheckedCurrent(); + if (isolate == NULL || !isolate->IsInitialized() || + IsDeadCheck(isolate, "v8::V8::AdjustAmountOfExternalAllocatedMemory()")) { return 0; } return isolate->heap()->AdjustAmountOfExternalAllocatedMemory( @@ -5779,7 +5954,8 @@ bool Debug::SetDebugEventListener(EventCallback that, Handle<Value> data) { foreign = isolate->factory()->NewForeign(FUNCTION_ADDR(EventCallbackWrapper)); } - isolate->debugger()->SetEventListener(foreign, Utils::OpenHandle(*data)); + isolate->debugger()->SetEventListener(foreign, + Utils::OpenHandle(*data, true)); return true; } @@ -5794,7 +5970,8 @@ bool Debug::SetDebugEventListener2(EventCallback2 that, Handle<Value> data) { if (that != NULL) { foreign = isolate->factory()->NewForeign(FUNCTION_ADDR(that)); } - isolate->debugger()->SetEventListener(foreign, Utils::OpenHandle(*data)); + isolate->debugger()->SetEventListener(foreign, + Utils::OpenHandle(*data, true)); return true; } @@ -5805,7 +5982,7 @@ bool Debug::SetDebugEventListener(v8::Handle<v8::Object> that, ON_BAILOUT(isolate, "v8::Debug::SetDebugEventListener()", return false); ENTER_V8(isolate); isolate->debugger()->SetEventListener(Utils::OpenHandle(*that), - Utils::OpenHandle(*data)); + Utils::OpenHandle(*data, true)); return true; } @@ -5944,7 +6121,7 @@ Local<Value> Debug::GetMirror(v8::Handle<v8::Value> obj) { v8::HandleScope scope; i::Debug* isolate_debug = isolate->debug(); isolate_debug->Load(); - i::Handle<i::JSObject> debug(isolate_debug->debug_context()->global()); + i::Handle<i::JSObject> debug(isolate_debug->debug_context()->global_object()); i::Handle<i::String> name = isolate->factory()->LookupAsciiSymbol("MakeMirror"); i::Handle<i::Object> fun_obj = i::GetProperty(debug, name); @@ -5976,6 +6153,7 @@ void Debug::ProcessDebugMessages() { i::Execution::ProcessDebugMessages(true); } + Local<Context> Debug::GetDebugContext() { i::Isolate* isolate = i::Isolate::Current(); EnsureInitializedForIsolate(isolate, "v8::Debug::GetDebugContext()"); @@ -5983,6 +6161,20 @@ Local<Context> Debug::GetDebugContext() { return Utils::ToLocal(i::Isolate::Current()->debugger()->GetDebugContext()); } + +void Debug::SetLiveEditEnabled(bool enable, Isolate* isolate) { + // If no isolate is supplied, use the default isolate. + i::Debugger* debugger; + if (isolate != NULL) { + i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate); + debugger = internal_isolate->debugger(); + } else { + debugger = i::Isolate::GetDefaultIsolateDebugger(); + } + debugger->set_live_edit_enabled(enable); +} + + #endif // ENABLE_DEBUGGER_SUPPORT @@ -6252,13 +6444,6 @@ int HeapGraphNode::GetSelfSize() const { } -int HeapGraphNode::GetRetainedSize() const { - i::Isolate* isolate = i::Isolate::Current(); - IsDeadCheck(isolate, "v8::HeapSnapshot::GetRetainedSize"); - return ToInternal(this)->retained_size(); -} - - int HeapGraphNode::GetChildrenCount() const { i::Isolate* isolate = i::Isolate::Current(); IsDeadCheck(isolate, "v8::HeapSnapshot::GetChildrenCount"); @@ -6274,28 +6459,6 @@ const HeapGraphEdge* HeapGraphNode::GetChild(int index) const { } -int HeapGraphNode::GetRetainersCount() const { - i::Isolate* isolate = i::Isolate::Current(); - IsDeadCheck(isolate, "v8::HeapSnapshot::GetRetainersCount"); - return ToInternal(this)->retainers().length(); -} - - -const HeapGraphEdge* HeapGraphNode::GetRetainer(int index) const { - i::Isolate* isolate = i::Isolate::Current(); - IsDeadCheck(isolate, "v8::HeapSnapshot::GetRetainer"); - return reinterpret_cast<const HeapGraphEdge*>( - ToInternal(this)->retainers()[index]); -} - - -const HeapGraphNode* HeapGraphNode::GetDominatorNode() const { - i::Isolate* isolate = i::Isolate::Current(); - IsDeadCheck(isolate, "v8::HeapSnapshot::GetDominatorNode"); - return reinterpret_cast<const HeapGraphNode*>(ToInternal(this)->dominator()); -} - - v8::Handle<v8::Value> HeapGraphNode::GetHeapValue() const { i::Isolate* isolate = i::Isolate::Current(); IsDeadCheck(isolate, "v8::HeapGraphNode::GetHeapValue"); @@ -6465,7 +6628,7 @@ void HeapProfiler::StopHeapObjectsTracking() { } -void HeapProfiler::PushHeapObjectsStats(OutputStream* stream) { +SnapshotObjectId HeapProfiler::PushHeapObjectsStats(OutputStream* stream) { i::Isolate* isolate = i::Isolate::Current(); IsDeadCheck(isolate, "v8::HeapProfiler::PushHeapObjectsStats"); return i::HeapProfiler::PushHeapObjectsStats(stream); @@ -6492,6 +6655,11 @@ int HeapProfiler::GetPersistentHandleCount() { } +size_t HeapProfiler::GetMemorySizeUsedByProfiler() { + return i::HeapProfiler::GetMemorySizeUsedByProfiler(); +} + + v8::Testing::StressType internal::Testing::stress_type_ = v8::Testing::kStressTypeOpt; @@ -6553,6 +6721,7 @@ void Testing::PrepareStressRun(int run) { void Testing::DeoptimizeAll() { + i::HandleScope scope; internal::Deoptimizer::DeoptimizeAll(); } @@ -6591,12 +6760,28 @@ char* HandleScopeImplementer::RestoreThread(char* storage) { void HandleScopeImplementer::IterateThis(ObjectVisitor* v) { +#ifdef DEBUG + bool found_block_before_deferred = false; +#endif // Iterate over all handles in the blocks except for the last. for (int i = blocks()->length() - 2; i >= 0; --i) { Object** block = blocks()->at(i); - v->VisitPointers(block, &block[kHandleBlockSize]); + if (last_handle_before_deferred_block_ != NULL && + (last_handle_before_deferred_block_ < &block[kHandleBlockSize]) && + (last_handle_before_deferred_block_ >= block)) { + v->VisitPointers(block, last_handle_before_deferred_block_); + ASSERT(!found_block_before_deferred); +#ifdef DEBUG + found_block_before_deferred = true; +#endif + } else { + v->VisitPointers(block, &block[kHandleBlockSize]); + } } + ASSERT(last_handle_before_deferred_block_ == NULL || + found_block_before_deferred); + // Iterate over live handles in the last block (if any). if (!blocks()->is_empty()) { v->VisitPointers(blocks()->last(), handle_scope_data_.next); @@ -6624,4 +6809,66 @@ char* HandleScopeImplementer::Iterate(ObjectVisitor* v, char* storage) { return storage + ArchiveSpacePerThread(); } + +DeferredHandles* HandleScopeImplementer::Detach(Object** prev_limit) { + DeferredHandles* deferred = + new DeferredHandles(isolate()->handle_scope_data()->next, isolate()); + + while (!blocks_.is_empty()) { + Object** block_start = blocks_.last(); + Object** block_limit = &block_start[kHandleBlockSize]; + // We should not need to check for NoHandleAllocation here. Assert + // this. + ASSERT(prev_limit == block_limit || + !(block_start <= prev_limit && prev_limit <= block_limit)); + if (prev_limit == block_limit) break; + deferred->blocks_.Add(blocks_.last()); + blocks_.RemoveLast(); + } + + // deferred->blocks_ now contains the blocks installed on the + // HandleScope stack since BeginDeferredScope was called, but in + // reverse order. + + ASSERT(prev_limit == NULL || !blocks_.is_empty()); + + ASSERT(!blocks_.is_empty() && prev_limit != NULL); + ASSERT(last_handle_before_deferred_block_ != NULL); + last_handle_before_deferred_block_ = NULL; + return deferred; +} + + +void HandleScopeImplementer::BeginDeferredScope() { + ASSERT(last_handle_before_deferred_block_ == NULL); + last_handle_before_deferred_block_ = isolate()->handle_scope_data()->next; +} + + +DeferredHandles::~DeferredHandles() { + isolate_->UnlinkDeferredHandles(this); + + for (int i = 0; i < blocks_.length(); i++) { +#ifdef DEBUG + HandleScope::ZapRange(blocks_[i], &blocks_[i][kHandleBlockSize]); +#endif + isolate_->handle_scope_implementer()->ReturnBlock(blocks_[i]); + } +} + + +void DeferredHandles::Iterate(ObjectVisitor* v) { + ASSERT(!blocks_.is_empty()); + + ASSERT((first_block_limit_ >= blocks_.first()) && + (first_block_limit_ <= &(blocks_.first())[kHandleBlockSize])); + + v->VisitPointers(blocks_.first(), first_block_limit_); + + for (int i = 1; i < blocks_.length(); i++) { + v->VisitPointers(blocks_[i], &blocks_[i][kHandleBlockSize]); + } +} + + } } // namespace v8::internal |