Remove QtV8 library from QtBase

The QtV8 library is going to live in the qtjsbackend module.

Change-Id: I72251316163829411dda998b9503ce6f75b3606a
Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@nokia.com>
Reviewed-by: Aaron Kennedy <aaron.kennedy@nokia.com>
Reviewed-by: Kent Hansen <kent.hansen@nokia.com>
Reviewed-by: Rohan McGovern <rohan.mcgovern@nokia.com>
This commit is contained in:
Simon Hausmann 2012-01-05 10:38:10 +01:00 committed by Qt by Nokia
parent 159098719b
commit 51d634ce2e
33 changed files with 0 additions and 5768 deletions

3
.gitignore vendored
View File

@ -128,13 +128,10 @@ src/openvg/qtopenvgversion.h
src/sql/qtsqlversion.h src/sql/qtsqlversion.h
src/testlib/qttestversion.h src/testlib/qttestversion.h
src/xml/qtxmlversion.h src/xml/qtxmlversion.h
src/v8/qtv8version.h
src/platformsupport/qtplatformsupportversion.h src/platformsupport/qtplatformsupportversion.h
src/printsupport/qtprintsupportversion.h src/printsupport/qtprintsupportversion.h
src/widgets/qtwidgetsversion.h src/widgets/qtwidgetsversion.h
src/v8/generated-debug/
# Test generated files # Test generated files
QObject.log QObject.log
tst_* tst_*

3
.gitmodules vendored
View File

@ -1,3 +0,0 @@
[submodule "src/3rdparty/v8"]
path = src/3rdparty/v8
url = git://github.com/aaronkennedy/v8.git

1
src/3rdparty/v8 vendored

@ -1 +0,0 @@
Subproject commit a07f617da094b83b7a9e5b2d37e8bf9172c61109

View File

@ -1,16 +0,0 @@
QT.v8.VERSION = 5.0.0
QT.v8.MAJOR_VERSION = 5
QT.v8.MINOR_VERSION = 0
QT.v8.PATCH_VERSION = 0
QT.v8.name = QtV8
QT.v8.bins = $$QT_MODULE_BIN_BASE
QT.v8.includes = $$QT_MODULE_INCLUDE_BASE/QtV8
QT.v8.private_includes = $$QT_MODULE_INCLUDE_BASE/QtV8/$$QT.v8.VERSION
QT.v8.sources = $$QT_MODULE_BASE/src/v8
QT.v8.libs = $$QT_MODULE_LIB_BASE
QT.v8.plugins = $$QT_MODULE_PLUGIN_BASE
QT.v8.imports = $$QT_MODULE_IMPORT_BASE
QT.v8.depends =
QT.v8.DEFINES =
!contains(QT_CONFIG, static): QT.v8.DEFINES += V8_SHARED USING_V8_SHARED

View File

@ -10,7 +10,6 @@ nacl: SRC_SUBDIRS -= src_network src_testlib
contains(QT_CONFIG, dbus):SRC_SUBDIRS += src_dbus contains(QT_CONFIG, dbus):SRC_SUBDIRS += src_dbus
contains(QT_CONFIG, no-gui): SRC_SUBDIRS -= src_gui contains(QT_CONFIG, no-gui): SRC_SUBDIRS -= src_gui
contains(QT_CONFIG, v8): SRC_SUBDIRS += src_v8
contains(QT_CONFIG, opengl)|contains(QT_CONFIG, opengles1)|contains(QT_CONFIG, opengles2): SRC_SUBDIRS += src_opengl contains(QT_CONFIG, opengl)|contains(QT_CONFIG, opengles1)|contains(QT_CONFIG, opengles2): SRC_SUBDIRS += src_opengl
SRC_SUBDIRS += src_plugins SRC_SUBDIRS += src_plugins
@ -19,8 +18,6 @@ src_winmain.subdir = $$QT_SOURCE_TREE/src/winmain
src_winmain.target = sub-winmain src_winmain.target = sub-winmain
src_corelib.subdir = $$QT_SOURCE_TREE/src/corelib src_corelib.subdir = $$QT_SOURCE_TREE/src/corelib
src_corelib.target = sub-corelib src_corelib.target = sub-corelib
src_v8.subdir = $$QT_SOURCE_TREE/src/v8
src_v8.target = sub-v8
src_xml.subdir = $$QT_SOURCE_TREE/src/xml src_xml.subdir = $$QT_SOURCE_TREE/src/xml
src_xml.target = sub-xml src_xml.target = sub-xml
src_dbus.subdir = $$QT_SOURCE_TREE/src/dbus src_dbus.subdir = $$QT_SOURCE_TREE/src/dbus
@ -65,7 +62,6 @@ src_platformsupport.target = sub-platformsupport
src_declarative.depends += src_opengl src_declarative.depends += src_opengl
src_webkit.depends += src_opengl src_webkit.depends += src_opengl
} }
contains(QT_CONFIG, v8snapshot):src_v8.depends += src_tools_mkv8snapshot
} }

View File

@ -1,39 +0,0 @@
TEMPLATE = app
TARGET = mkv8snapshot
QT =
CONFIG -= app_bundle
CONFIG -= qt
CONFIG += console
CONFIG += warn_off
DESTDIR = ../../../bin
INCLUDEPATH += .
DEPENDPATH += .
LIBS =
OBJECTS_DIR = .
contains(QT_CONFIG, build_all): CONFIG += build_all
win32|mac:!macx-xcode: CONFIG += debug_and_release
TARGET = $$TARGET$$qtPlatformTargetSuffix()
cross_compile {
equals(QT_ARCH, arm): V8_TARGET_ARCH = arm
}
include(../../v8/v8.pri)
cross_compile {
equals(V8_TARGET_ARCH, arm): SOURCES += $$V8SRC/arm/simulator-arm.cc
}
SOURCES += \
$$V8SRC/snapshot-empty.cc \
$$V8SRC/mksnapshot.cc
unix:LIBS += -lpthread
# We don't need to install this tool, it's only used for building v8.
# However we do have to make sure that 'make install' builds it.
dummytarget.CONFIG = dummy_install
INSTALLS += dummytarget

View File

@ -2,7 +2,6 @@ TEMPLATE = subdirs
TOOLS_SUBDIRS = src_tools_bootstrap src_tools_moc src_tools_rcc TOOLS_SUBDIRS = src_tools_bootstrap src_tools_moc src_tools_rcc
!contains(QT_CONFIG, no-gui): TOOLS_SUBDIRS += src_tools_uic !contains(QT_CONFIG, no-gui): TOOLS_SUBDIRS += src_tools_uic
contains(QT_CONFIG, v8):contains(QT_CONFIG, v8snapshot): TOOLS_SUBDIRS += src_tools_mkv8snapshot
# Set subdir and respective target name # Set subdir and respective target name
src_tools_bootstrap.subdir = $$QT_SOURCE_TREE/src/tools/bootstrap src_tools_bootstrap.subdir = $$QT_SOURCE_TREE/src/tools/bootstrap
src_tools_bootstrap.target = sub-tools-bootstrap src_tools_bootstrap.target = sub-tools-bootstrap
@ -12,8 +11,6 @@ src_tools_rcc.subdir = $$QT_SOURCE_TREE/src/tools/rcc
src_tools_rcc.target = sub-rcc src_tools_rcc.target = sub-rcc
src_tools_uic.subdir = $$QT_SOURCE_TREE/src/tools/uic src_tools_uic.subdir = $$QT_SOURCE_TREE/src/tools/uic
src_tools_uic.target = sub-uic src_tools_uic.target = sub-uic
src_tools_mkv8snapshot.subdir = $$QT_SOURCE_TREE/src/tools/mkv8snapshot
src_tools_mkv8snapshot.target = sub-mkv8snapshot
!wince*:!ordered { !wince*:!ordered {
# Set dependencies for each subdir # Set dependencies for each subdir

View File

@ -1,336 +0,0 @@
From d97195f011cdaa8b859d759f8a34dd50c3092f30 Mon Sep 17 00:00:00 2001
From: Aaron Kennedy <aaron.kennedy@nokia.com>
Date: Tue, 4 Oct 2011 15:04:21 +1000
Subject: [PATCH 01/13] Add hashing and comparison methods to v8::String
This allows us to more rapidly search for a v8::String inside a hash
of QStrings.
---
include/v8.h | 45 +++++++++++++++++++++++++++++
src/api.cc | 51 +++++++++++++++++++++++++++++++++
src/heap-inl.h | 2 +
src/heap.cc | 3 ++
src/objects-inl.h | 1 +
src/objects.cc | 82 ++++++++++++++++++++++++++++++++++++++++++++++++++++-
src/objects.h | 10 ++++++-
7 files changed, 192 insertions(+), 2 deletions(-)
diff --git a/include/v8.h b/include/v8.h
index 73b7fbe..86ea70f 100644
--- a/include/v8.h
+++ b/include/v8.h
@@ -1021,6 +1021,49 @@ class String : public Primitive {
V8EXPORT int Utf8Length() const;
/**
+ * Returns the hash of this string.
+ */
+ V8EXPORT uint32_t Hash() const;
+
+ struct CompleteHashData {
+ CompleteHashData() : length(0), hash(0), symbol_id(0) {}
+ int length;
+ uint32_t hash;
+ uint32_t symbol_id;
+ };
+
+ /**
+ * Returns the "complete" hash of the string. This is
+ * all the information about the string needed to implement
+ * a very efficient hash keyed on the string.
+ *
+ * The members of CompleteHashData are:
+ * length: The length of the string. Equivalent to Length()
+ * hash: The hash of the string. Equivalent to Hash()
+ * symbol_id: If the string is a sequential symbol, the symbol
+ * id, otherwise 0. If the symbol ids of two strings are
+ * the same (and non-zero) the two strings are identical.
+ * If the symbol ids are different the strings may still be
+ * identical, but an Equals() check must be performed.
+ */
+ V8EXPORT CompleteHashData CompleteHash() const;
+
+ /**
+ * Compute a hash value for the passed UTF16 string
+ * data.
+ */
+ V8EXPORT static uint32_t ComputeHash(uint16_t *string, int length);
+ V8EXPORT static uint32_t ComputeHash(char *string, int length);
+
+ /**
+ * Returns true if this string is equal to the external
+ * string data provided.
+ */
+ V8EXPORT bool Equals(uint16_t *string, int length);
+ V8EXPORT bool Equals(char *string, int length);
+ inline bool Equals(Handle<Value> that) const { return v8::Value::Equals(that); }
+
+ /**
* Write the contents of the string to an external buffer.
* If no arguments are given, expects the buffer to be large
* enough to hold the entire string and NULL terminator. Copies
@@ -1051,6 +1094,8 @@ class String : public Primitive {
NO_NULL_TERMINATION = 2
};
+ V8EXPORT uint16_t GetCharacter(int index);
+
// 16-bit character codes.
V8EXPORT int Write(uint16_t* buffer,
int start = 0,
diff --git a/src/api.cc b/src/api.cc
index ac4f07f..996812e 100644
--- a/src/api.cc
+++ b/src/api.cc
@@ -3633,6 +3633,57 @@ int String::Utf8Length() const {
}
+uint32_t String::Hash() const {
+ i::Handle<i::String> str = Utils::OpenHandle(this);
+ if (IsDeadCheck(str->GetIsolate(), "v8::String::Hash()")) return 0;
+ return str->Hash();
+}
+
+
+String::CompleteHashData String::CompleteHash() const {
+ i::Handle<i::String> str = Utils::OpenHandle(this);
+ if (IsDeadCheck(str->GetIsolate(), "v8::String::CompleteHash()")) return CompleteHashData();
+ CompleteHashData result;
+ result.length = str->length();
+ result.hash = str->Hash();
+ if (str->IsSeqString())
+ result.symbol_id = i::SeqString::cast(*str)->symbol_id();
+ return result;
+}
+
+
+uint32_t String::ComputeHash(uint16_t *string, int length) {
+ return i::HashSequentialString<i::uc16>(string, length) >> i::String::kHashShift;
+}
+
+
+uint32_t String::ComputeHash(char *string, int length) {
+ return i::HashSequentialString<char>(string, length) >> i::String::kHashShift;
+}
+
+
+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,
diff --git a/src/heap-inl.h b/src/heap-inl.h
index aaf2927..4c55d63 100644
--- a/src/heap-inl.h
+++ b/src/heap-inl.h
@@ -105,6 +105,7 @@ MaybeObject* Heap::AllocateAsciiSymbol(Vector<const char> str,
String* answer = String::cast(result);
answer->set_length(str.length());
answer->set_hash_field(hash_field);
+ SeqString::cast(answer)->set_symbol_id(0);
ASSERT_EQ(size, answer->Size());
@@ -138,6 +139,7 @@ MaybeObject* Heap::AllocateTwoByteSymbol(Vector<const uc16> str,
String* answer = String::cast(result);
answer->set_length(str.length());
answer->set_hash_field(hash_field);
+ SeqString::cast(answer)->set_symbol_id(0);
ASSERT_EQ(size, answer->Size());
diff --git a/src/heap.cc b/src/heap.cc
index bbb9d3e..d287ead 100644
--- a/src/heap.cc
+++ b/src/heap.cc
@@ -4009,6 +4009,7 @@ MaybeObject* Heap::AllocateInternalSymbol(unibrow::CharacterStream* buffer,
String* answer = String::cast(result);
answer->set_length(chars);
answer->set_hash_field(hash_field);
+ SeqString::cast(answer)->set_symbol_id(0);
ASSERT_EQ(size, answer->Size());
@@ -4051,6 +4052,7 @@ MaybeObject* Heap::AllocateRawAsciiString(int length, PretenureFlag pretenure) {
HeapObject::cast(result)->set_map(ascii_string_map());
String::cast(result)->set_length(length);
String::cast(result)->set_hash_field(String::kEmptyHashField);
+ SeqString::cast(result)->set_symbol_id(0);
ASSERT_EQ(size, HeapObject::cast(result)->Size());
return result;
}
@@ -4086,6 +4088,7 @@ MaybeObject* Heap::AllocateRawTwoByteString(int length,
HeapObject::cast(result)->set_map(string_map());
String::cast(result)->set_length(length);
String::cast(result)->set_hash_field(String::kEmptyHashField);
+ SeqString::cast(result)->set_symbol_id(0);
ASSERT_EQ(size, HeapObject::cast(result)->Size());
return result;
}
diff --git a/src/objects-inl.h b/src/objects-inl.h
index dc3aa46..34cae9f 100644
--- a/src/objects-inl.h
+++ b/src/objects-inl.h
@@ -2082,6 +2082,7 @@ SMI_ACCESSORS(FixedArrayBase, length, kLengthOffset)
SMI_ACCESSORS(FreeSpace, size, kSizeOffset)
SMI_ACCESSORS(String, length, kLengthOffset)
+SMI_ACCESSORS(SeqString, symbol_id, kSymbolIdOffset)
uint32_t String::hash_field() {
diff --git a/src/objects.cc b/src/objects.cc
index 9a87ac5..2946d02 100644
--- a/src/objects.cc
+++ b/src/objects.cc
@@ -6716,6 +6716,71 @@ static inline bool CompareStringContentsPartial(Isolate* isolate,
}
+bool String::SlowEqualsExternal(uc16 *string, int length) {
+ int len = this->length();
+ if (len != length) return false;
+ if (len == 0) return true;
+
+ // We know the strings are both non-empty. Compare the first chars
+ // before we try to flatten the strings.
+ if (this->Get(0) != string[0]) return false;
+
+ String* lhs = this->TryFlattenGetString();
+
+ if (lhs->IsFlat()) {
+ String::FlatContent lhs_content = lhs->GetFlatContent();
+ if (lhs->IsAsciiRepresentation()) {
+ Vector<const char> vec1 = lhs_content.ToAsciiVector();
+ VectorIterator<char> buf1(vec1);
+ VectorIterator<uc16> ib(string, length);
+ return CompareStringContents(&buf1, &ib);
+ } else {
+ Vector<const uc16> vec1 = lhs_content.ToUC16Vector();
+ Vector<const uc16> vec2(string, length);
+ return CompareRawStringContents(vec1, vec2);
+ }
+ } else {
+ Isolate* isolate = GetIsolate();
+ isolate->objects_string_compare_buffer_a()->Reset(0, lhs);
+ VectorIterator<uc16> ib(string, length);
+ return CompareStringContents(isolate->objects_string_compare_buffer_a(), &ib);
+ }
+}
+
+
+bool String::SlowEqualsExternal(char *string, int length)
+{
+ int len = this->length();
+ if (len != length) return false;
+ if (len == 0) return true;
+
+ // We know the strings are both non-empty. Compare the first chars
+ // before we try to flatten the strings.
+ if (this->Get(0) != string[0]) return false;
+
+ String* lhs = this->TryFlattenGetString();
+
+ if (StringShape(lhs).IsSequentialAscii()) {
+ const char* str1 = SeqAsciiString::cast(lhs)->GetChars();
+ return CompareRawStringContents(Vector<const char>(str1, len),
+ Vector<const char>(string, len));
+ }
+
+ if (lhs->IsFlat()) {
+ String::FlatContent lhs_content = lhs->GetFlatContent();
+ Vector<const uc16> vec1 = lhs_content.ToUC16Vector();
+ VectorIterator<const uc16> buf1(vec1);
+ VectorIterator<char> buf2(string, length);
+ return CompareStringContents(&buf1, &buf2);
+ } else {
+ Isolate* isolate = GetIsolate();
+ isolate->objects_string_compare_buffer_a()->Reset(0, lhs);
+ VectorIterator<char> ib(string, length);
+ return CompareStringContents(isolate->objects_string_compare_buffer_a(), &ib);
+ }
+}
+
+
bool String::SlowEquals(String* other) {
// Fast check: negative check with lengths.
int len = length();
@@ -10716,9 +10781,24 @@ class AsciiSymbolKey : public SequentialSymbolKey<char> {
MaybeObject* AsObject() {
if (hash_field_ == 0) Hash();
- return HEAP->AllocateAsciiSymbol(string_, hash_field_);
+ MaybeObject *result = HEAP->AllocateAsciiSymbol(string_, hash_field_);
+ if (!result->IsFailure() && result->ToObjectUnchecked()->IsSeqString()) {
+ while (true) {
+ Atomic32 my_symbol_id = next_symbol_id;
+ if (my_symbol_id > Smi::kMaxValue)
+ break;
+ if (my_symbol_id == NoBarrier_CompareAndSwap(&next_symbol_id, my_symbol_id, my_symbol_id + 1)) {
+ SeqString::cast(result->ToObjectUnchecked())->set_symbol_id(my_symbol_id);
+ break;
+ }
+ }
+ }
+ return result;
}
+
+ static Atomic32 next_symbol_id;
};
+Atomic32 AsciiSymbolKey::next_symbol_id = 1;
class SubStringAsciiSymbolKey : public HashTableKey {
diff --git a/src/objects.h b/src/objects.h
index f7d2180..d96e5f9 100644
--- a/src/objects.h
+++ b/src/objects.h
@@ -6201,6 +6201,9 @@ class String: public HeapObject {
bool IsAsciiEqualTo(Vector<const char> str);
bool IsTwoByteEqualTo(Vector<const uc16> str);
+ bool SlowEqualsExternal(uc16 *string, int length);
+ bool SlowEqualsExternal(char *string, int length);
+
// Return a UTF8 representation of the string. The string is null
// terminated but may optionally contain nulls. Length is returned
// in length_output if length_output is not a null pointer The string
@@ -6457,8 +6460,13 @@ class SeqString: public String {
// Casting.
static inline SeqString* cast(Object* obj);
+ // Get and set the symbol id of the string
+ inline int symbol_id();
+ inline void set_symbol_id(int value);
+
// Layout description.
- static const int kHeaderSize = String::kSize;
+ static const int kSymbolIdOffset = String::kSize;
+ static const int kHeaderSize = kSymbolIdOffset + kPointerSize;
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(SeqString);
--
1.7.4.1

View File

@ -1,361 +0,0 @@
From e30b202d683e36731d9674ebf75803990a33816e Mon Sep 17 00:00:00 2001
From: Aaron Kennedy <aaron.kennedy@nokia.com>
Date: Thu, 27 Oct 2011 11:31:56 +0100
Subject: [PATCH 02/13] Add a "fallback" mode for named property interceptors
By default interceptors are called before the normal property
resolution on objects. When an interceptor is installed as a
"fallback" interceptor, it is only called if the object doesn't
already have the property.
In the case of a global object having an fallback interceptor,
the interceptor is not invoked at all for var or function
declarations.
---
include/v8.h | 7 +++++++
src/api.cc | 29 +++++++++++++++++++++++++++++
src/factory.cc | 3 +++
src/handles.cc | 6 ++++--
src/handles.h | 3 ++-
src/objects-inl.h | 15 +++++++++++++++
src/objects.cc | 24 +++++++++++++++++-------
src/objects.h | 16 ++++++++++++----
src/runtime.cc | 11 ++++++-----
9 files changed, 95 insertions(+), 19 deletions(-)
diff --git a/include/v8.h b/include/v8.h
index 86ea70f..d2e6c32 100644
--- a/include/v8.h
+++ b/include/v8.h
@@ -2305,6 +2305,7 @@ class V8EXPORT FunctionTemplate : public Template {
NamedPropertyQuery query,
NamedPropertyDeleter remover,
NamedPropertyEnumerator enumerator,
+ bool is_fallback,
Handle<Value> data);
void SetIndexedInstancePropertyHandler(IndexedPropertyGetter getter,
IndexedPropertySetter setter,
@@ -2388,6 +2389,12 @@ class V8EXPORT ObjectTemplate : public Template {
NamedPropertyDeleter deleter = 0,
NamedPropertyEnumerator enumerator = 0,
Handle<Value> data = Handle<Value>());
+ void SetFallbackPropertyHandler(NamedPropertyGetter getter,
+ NamedPropertySetter setter = 0,
+ NamedPropertyQuery query = 0,
+ NamedPropertyDeleter deleter = 0,
+ NamedPropertyEnumerator enumerator = 0,
+ Handle<Value> data = Handle<Value>());
/**
* Sets an indexed property handler on the object template.
diff --git a/src/api.cc b/src/api.cc
index 996812e..e0f3b5a 100644
--- a/src/api.cc
+++ b/src/api.cc
@@ -1123,6 +1123,7 @@ void FunctionTemplate::SetNamedInstancePropertyHandler(
NamedPropertyQuery query,
NamedPropertyDeleter remover,
NamedPropertyEnumerator enumerator,
+ bool is_fallback,
Handle<Value> data) {
i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
if (IsDeadCheck(isolate,
@@ -1141,6 +1142,7 @@ void FunctionTemplate::SetNamedInstancePropertyHandler(
if (query != 0) SET_FIELD_WRAPPED(obj, set_query, query);
if (remover != 0) SET_FIELD_WRAPPED(obj, set_deleter, remover);
if (enumerator != 0) SET_FIELD_WRAPPED(obj, set_enumerator, enumerator);
+ obj->set_is_fallback(i::Smi::FromInt(is_fallback));
if (data.IsEmpty()) data = v8::Undefined();
obj->set_data(*Utils::OpenHandle(*data));
@@ -1285,6 +1287,33 @@ void ObjectTemplate::SetNamedPropertyHandler(NamedPropertyGetter getter,
query,
remover,
enumerator,
+ false,
+ data);
+}
+
+
+void ObjectTemplate::SetFallbackPropertyHandler(NamedPropertyGetter getter,
+ NamedPropertySetter setter,
+ NamedPropertyQuery query,
+ NamedPropertyDeleter remover,
+ NamedPropertyEnumerator enumerator,
+ Handle<Value> data) {
+ i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
+ if (IsDeadCheck(isolate, "v8::ObjectTemplate::SetNamedPropertyHandler()")) {
+ return;
+ }
+ ENTER_V8(isolate);
+ i::HandleScope scope(isolate);
+ EnsureConstructor(this);
+ i::FunctionTemplateInfo* constructor =
+ i::FunctionTemplateInfo::cast(Utils::OpenHandle(this)->constructor());
+ i::Handle<i::FunctionTemplateInfo> cons(constructor);
+ Utils::ToLocal(cons)->SetNamedInstancePropertyHandler(getter,
+ setter,
+ query,
+ remover,
+ enumerator,
+ true,
data);
}
diff --git a/src/factory.cc b/src/factory.cc
index 15f640e..1b95ed1 100644
--- a/src/factory.cc
+++ b/src/factory.cc
@@ -1213,6 +1213,9 @@ Handle<JSFunction> Factory::CreateApiFunction(
// Set interceptor information in the map.
if (!obj->named_property_handler()->IsUndefined()) {
map->set_has_named_interceptor();
+ InterceptorInfo *nph = InterceptorInfo::cast(obj->named_property_handler());
+ bool is_fallback = nph->is_fallback()->IsUndefined()?false:nph->is_fallback()->value();
+ map->set_named_interceptor_is_fallback(is_fallback);
}
if (!obj->indexed_property_handler()->IsUndefined()) {
map->set_has_indexed_interceptor();
diff --git a/src/handles.cc b/src/handles.cc
index 62851f3..790d224 100644
--- a/src/handles.cc
+++ b/src/handles.cc
@@ -269,9 +269,11 @@ Handle<Object> SetProperty(Handle<JSReceiver> object,
Handle<String> key,
Handle<Object> value,
PropertyAttributes attributes,
- StrictModeFlag strict_mode) {
+ StrictModeFlag strict_mode,
+ bool skip_fallback_interceptor) {
CALL_HEAP_FUNCTION(object->GetIsolate(),
- object->SetProperty(*key, *value, attributes, strict_mode),
+ object->SetProperty(*key, *value, attributes, strict_mode,
+ skip_fallback_interceptor),
Object);
}
diff --git a/src/handles.h b/src/handles.h
index 06e47fc..c359cb3 100644
--- a/src/handles.h
+++ b/src/handles.h
@@ -190,7 +190,8 @@ Handle<Object> SetProperty(Handle<JSReceiver> object,
Handle<String> key,
Handle<Object> value,
PropertyAttributes attributes,
- StrictModeFlag strict_mode);
+ StrictModeFlag strict_mode,
+ bool skip_fallback_interceptor = false);
Handle<Object> SetProperty(Handle<Object> object,
Handle<Object> key,
diff --git a/src/objects-inl.h b/src/objects-inl.h
index 34cae9f..1cfea84 100644
--- a/src/objects-inl.h
+++ b/src/objects-inl.h
@@ -2754,6 +2754,20 @@ void Map::set_is_shared(bool value) {
bool Map::is_shared() {
return ((1 << kIsShared) & bit_field3()) != 0;
}
+
+void Map::set_named_interceptor_is_fallback(bool value)
+{
+ if (value) {
+ set_bit_field3(bit_field3() | (1 << kNamedInterceptorIsFallback));
+ } else {
+ set_bit_field3(bit_field3() & ~(1 << kNamedInterceptorIsFallback));
+ }
+}
+
+bool Map::named_interceptor_is_fallback()
+{
+ return ((1 << kNamedInterceptorIsFallback) & bit_field3()) != 0;
+}
JSFunction* Map::unchecked_constructor() {
@@ -3255,6 +3269,7 @@ ACCESSORS(InterceptorInfo, query, Object, kQueryOffset)
ACCESSORS(InterceptorInfo, deleter, Object, kDeleterOffset)
ACCESSORS(InterceptorInfo, enumerator, Object, kEnumeratorOffset)
ACCESSORS(InterceptorInfo, data, Object, kDataOffset)
+ACCESSORS(InterceptorInfo, is_fallback, Smi, kFallbackOffset)
ACCESSORS(CallHandlerInfo, callback, Object, kCallbackOffset)
ACCESSORS(CallHandlerInfo, data, Object, kDataOffset)
diff --git a/src/objects.cc b/src/objects.cc
index 2946d02..f5b6bee 100644
--- a/src/objects.cc
+++ b/src/objects.cc
@@ -1980,9 +1980,10 @@ MaybeObject* JSObject::SetPropertyWithInterceptor(
MaybeObject* JSReceiver::SetProperty(String* name,
Object* value,
PropertyAttributes attributes,
- StrictModeFlag strict_mode) {
+ StrictModeFlag strict_mode,
+ bool skip_fallback_interceptor) {
LookupResult result(GetIsolate());
- LocalLookup(name, &result);
+ LocalLookup(name, &result, skip_fallback_interceptor);
return SetProperty(&result, name, value, attributes, strict_mode);
}
@@ -4213,7 +4214,8 @@ AccessorDescriptor* Map::FindAccessor(String* name) {
}
-void JSReceiver::LocalLookup(String* name, LookupResult* result) {
+void JSReceiver::LocalLookup(String* name, LookupResult* result,
+ bool skip_fallback_interceptor) {
ASSERT(name->IsString());
Heap* heap = GetHeap();
@@ -4245,23 +4247,31 @@ void JSReceiver::LocalLookup(String* name, LookupResult* result) {
}
// Check for lookup interceptor except when bootstrapping.
- if (js_object->HasNamedInterceptor() &&
- !heap->isolate()->bootstrapper()->IsActive()) {
+ bool wouldIntercept = js_object->HasNamedInterceptor() &&
+ !heap->isolate()->bootstrapper()->IsActive();
+ if (wouldIntercept && !map()->named_interceptor_is_fallback()) {
result->InterceptorResult(js_object);
return;
}
js_object->LocalLookupRealNamedProperty(name, result);
+
+ if (wouldIntercept && !skip_fallback_interceptor && !result->IsProperty() &&
+ map()->named_interceptor_is_fallback()) {
+ result->InterceptorResult(js_object);
+ return;
+ }
}
-void JSReceiver::Lookup(String* name, LookupResult* result) {
+void JSReceiver::Lookup(String* name, LookupResult* result,
+ bool skip_fallback_interceptor) {
// Ecma-262 3rd 8.6.2.4
Heap* heap = GetHeap();
for (Object* current = this;
current != heap->null_value();
current = JSObject::cast(current)->GetPrototype()) {
- JSReceiver::cast(current)->LocalLookup(name, result);
+ JSReceiver::cast(current)->LocalLookup(name, result, skip_fallback_interceptor);
if (result->IsProperty()) return;
}
result->NotFound();
diff --git a/src/objects.h b/src/objects.h
index d96e5f9..ed40061 100644
--- a/src/objects.h
+++ b/src/objects.h
@@ -1362,7 +1362,8 @@ class JSReceiver: public HeapObject {
MUST_USE_RESULT MaybeObject* SetProperty(String* key,
Object* value,
PropertyAttributes attributes,
- StrictModeFlag strict_mode);
+ StrictModeFlag strict_mode,
+ bool skip_fallback_interceptor = false);
MUST_USE_RESULT MaybeObject* SetProperty(LookupResult* result,
String* key,
Object* value,
@@ -1414,8 +1415,8 @@ class JSReceiver: public HeapObject {
// Lookup a property. If found, the result is valid and has
// detailed information.
- void LocalLookup(String* name, LookupResult* result);
- void Lookup(String* name, LookupResult* result);
+ void LocalLookup(String* name, LookupResult* result, bool skip_fallback_interceptor = false);
+ void Lookup(String* name, LookupResult* result, bool skip_fallback_interceptor = false);
protected:
Smi* GenerateIdentityHash();
@@ -4242,6 +4243,10 @@ class Map: public HeapObject {
inline void set_is_access_check_needed(bool access_check_needed);
inline bool is_access_check_needed();
+ // Whether the named interceptor is a fallback interceptor or not
+ inline void set_named_interceptor_is_fallback(bool value);
+ inline bool named_interceptor_is_fallback();
+
// [prototype]: implicit prototype object.
DECL_ACCESSORS(prototype, Object)
@@ -4506,6 +4511,7 @@ class Map: public HeapObject {
// Bit positions for bit field 3
static const int kIsShared = 0;
+ static const int kNamedInterceptorIsFallback = 1;
// Layout of the default cache. It holds alternating name and code objects.
static const int kCodeCacheEntrySize = 2;
@@ -7390,6 +7396,7 @@ class InterceptorInfo: public Struct {
DECL_ACCESSORS(deleter, Object)
DECL_ACCESSORS(enumerator, Object)
DECL_ACCESSORS(data, Object)
+ DECL_ACCESSORS(is_fallback, Smi)
static inline InterceptorInfo* cast(Object* obj);
@@ -7409,7 +7416,8 @@ class InterceptorInfo: public Struct {
static const int kDeleterOffset = kQueryOffset + kPointerSize;
static const int kEnumeratorOffset = kDeleterOffset + kPointerSize;
static const int kDataOffset = kEnumeratorOffset + kPointerSize;
- static const int kSize = kDataOffset + kPointerSize;
+ static const int kFallbackOffset = kDataOffset + kPointerSize;
+ static const int kSize = kFallbackOffset + kPointerSize;
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(InterceptorInfo);
diff --git a/src/runtime.cc b/src/runtime.cc
index 9c23c2c..0e256c1 100644
--- a/src/runtime.cc
+++ b/src/runtime.cc
@@ -1330,7 +1330,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareGlobals) {
// Lookup the property in the global object, and don't set the
// value of the variable if the property is already there.
LookupResult lookup(isolate);
- global->Lookup(*name, &lookup);
+ global->Lookup(*name, &lookup, true);
if (lookup.IsProperty()) {
// We found an existing property. Unless it was an interceptor
// that claims the property is absent, skip this declaration.
@@ -1357,7 +1357,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareGlobals) {
}
LookupResult lookup(isolate);
- global->LocalLookup(*name, &lookup);
+ global->LocalLookup(*name, &lookup, true);
// Compute the property attributes. According to ECMA-262, section
// 13, page 71, the property must be read-only and
@@ -1398,7 +1398,8 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareGlobals) {
name,
value,
static_cast<PropertyAttributes>(attr),
- strict_mode));
+ strict_mode,
+ true));
}
}
@@ -1534,7 +1535,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeVarGlobal) {
while (object->IsJSObject() &&
JSObject::cast(object)->map()->is_hidden_prototype()) {
JSObject* raw_holder = JSObject::cast(object);
- raw_holder->LocalLookup(*name, &lookup);
+ raw_holder->LocalLookup(*name, &lookup, true);
if (lookup.IsProperty() && lookup.type() == INTERCEPTOR) {
HandleScope handle_scope(isolate);
Handle<JSObject> holder(raw_holder);
@@ -1557,7 +1558,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeVarGlobal) {
// Reload global in case the loop above performed a GC.
global = isolate->context()->global();
if (assign) {
- return global->SetProperty(*name, args[2], attributes, strict_mode);
+ return global->SetProperty(*name, args[2], attributes, strict_mode, true);
}
return isolate->heap()->undefined_value();
}
--
1.7.4.1

View File

@ -1,595 +0,0 @@
From 501255df9cb6241a1f6c8d8a3361b9582fa481ef Mon Sep 17 00:00:00 2001
From: Aaron Kennedy <aaron.kennedy@nokia.com>
Date: Tue, 4 Oct 2011 16:06:09 +1000
Subject: [PATCH 03/13] Generalize external object resources
V8 was already able to manage and finalize an external string
resource. This change generalizes that mechanism to handle a
single generic external resource - a v8::Object::ExternalResource
derived instance - on normal JSObject's.
This is useful for mapping C++ objects to JS objects where the
C++ object's memory is effectively owned by the JS Object, and
thus needs to destroyed when the JS Object is garbage collected.
The V8 mailing list suggests using a weak persistent handle for
this purpose, but that seems to incur a fairly massive performance
penalty for short lived objects as weak persistent handle callbacks
are not called until the object has been promoted into the old
object space.
---
include/v8.h | 25 ++++++++++++++++++++
src/api.cc | 56 +++++++++++++++++++++++++++++++++++++++++++++
src/factory.cc | 11 +++++++++
src/heap-inl.h | 63 +++++++++++++++++++++++++++++++++++---------------
src/heap.cc | 29 +++++++++++++++++------
src/heap.h | 16 ++++++++-----
src/mark-compact.cc | 13 +++++-----
src/objects-inl.h | 35 +++++++++++++++++++++++++++-
src/objects.h | 19 ++++++++++++---
9 files changed, 223 insertions(+), 44 deletions(-)
diff --git a/include/v8.h b/include/v8.h
index d2e6c32..3ef4dd6 100644
--- a/include/v8.h
+++ b/include/v8.h
@@ -1597,6 +1597,25 @@ class Object : public Value {
/** Sets a native pointer in an internal field. */
V8EXPORT void SetPointerInInternalField(int index, void* value);
+ class V8EXPORT ExternalResource { // NOLINT
+ public:
+ ExternalResource() {}
+ virtual ~ExternalResource() {}
+
+ protected:
+ virtual void Dispose() { delete this; }
+
+ private:
+ // Disallow copying and assigning.
+ ExternalResource(const ExternalResource&);
+ void operator=(const ExternalResource&);
+
+ friend class v8::internal::Heap;
+ };
+
+ V8EXPORT void SetExternalResource(ExternalResource *);
+ V8EXPORT ExternalResource *GetExternalResource();
+
// Testers for local properties.
V8EXPORT bool HasOwnProperty(Handle<String> key);
V8EXPORT bool HasRealNamedProperty(Handle<String> key);
@@ -2466,6 +2485,12 @@ class V8EXPORT ObjectTemplate : public Template {
*/
void SetInternalFieldCount(int value);
+ /**
+ * Sets whether the object can store an "external resource" object.
+ */
+ bool HasExternalResource();
+ void SetHasExternalResource(bool value);
+
private:
ObjectTemplate();
static Local<ObjectTemplate> New(Handle<FunctionTemplate> constructor);
diff --git a/src/api.cc b/src/api.cc
index e0f3b5a..7d54252 100644
--- a/src/api.cc
+++ b/src/api.cc
@@ -1436,6 +1436,34 @@ void ObjectTemplate::SetInternalFieldCount(int value) {
}
+bool ObjectTemplate::HasExternalResource()
+{
+ if (IsDeadCheck(Utils::OpenHandle(this)->GetIsolate(),
+ "v8::ObjectTemplate::HasExternalResource()")) {
+ return 0;
+ }
+ return !Utils::OpenHandle(this)->has_external_resource()->IsUndefined();
+}
+
+
+void ObjectTemplate::SetHasExternalResource(bool value)
+{
+ i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
+ if (IsDeadCheck(isolate, "v8::ObjectTemplate::SetHasExternalResource()")) {
+ return;
+ }
+ ENTER_V8(isolate);
+ if (value) {
+ EnsureConstructor(this);
+ }
+ if (value) {
+ Utils::OpenHandle(this)->set_has_external_resource(i::Smi::FromInt(1));
+ } else {
+ Utils::OpenHandle(this)->set_has_external_resource(Utils::OpenHandle(this)->GetHeap()->undefined_value());
+ }
+}
+
+
// --- S c r i p t D a t a ---
@@ -4029,6 +4057,34 @@ void v8::Object::SetPointerInInternalField(int index, void* value) {
}
+void v8::Object::SetExternalResource(v8::Object::ExternalResource *resource) {
+ i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
+ ENTER_V8(isolate);
+ i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
+ if (CanBeEncodedAsSmi(resource)) {
+ obj->SetExternalResourceObject(EncodeAsSmi(resource));
+ } else {
+ obj->SetExternalResourceObject(*isolate->factory()->NewForeign(static_cast<i::Address>((void *)resource)));
+ }
+ if (!obj->IsSymbol()) {
+ isolate->heap()->external_string_table()->AddObject(*obj);
+ }
+}
+
+
+v8::Object::ExternalResource *v8::Object::GetExternalResource() {
+ i::Handle<i::JSObject> obj = Utils::OpenHandle(this);
+ i::Object* value = obj->GetExternalResourceObject();
+ if (value->IsSmi()) {
+ return reinterpret_cast<v8::Object::ExternalResource*>(i::Internals::GetExternalPointerFromSmi(value));
+ } else if (value->IsForeign()) {
+ return reinterpret_cast<v8::Object::ExternalResource*>(i::Foreign::cast(value)->address());
+ } else {
+ return NULL;
+ }
+}
+
+
// --- E n v i r o n m e n t ---
diff --git a/src/factory.cc b/src/factory.cc
index 1b95ed1..8c96944 100644
--- a/src/factory.cc
+++ b/src/factory.cc
@@ -1152,15 +1152,21 @@ Handle<JSFunction> Factory::CreateApiFunction(
Handle<Code> construct_stub = isolate()->builtins()->JSConstructStubApi();
int internal_field_count = 0;
+ bool has_external_resource = false;
+
if (!obj->instance_template()->IsUndefined()) {
Handle<ObjectTemplateInfo> instance_template =
Handle<ObjectTemplateInfo>(
ObjectTemplateInfo::cast(obj->instance_template()));
internal_field_count =
Smi::cast(instance_template->internal_field_count())->value();
+ has_external_resource =
+ !instance_template->has_external_resource()->IsUndefined();
}
int instance_size = kPointerSize * internal_field_count;
+ if (has_external_resource) instance_size += kPointerSize;
+
InstanceType type = INVALID_TYPE;
switch (instance_type) {
case JavaScriptObject:
@@ -1195,6 +1201,11 @@ Handle<JSFunction> Factory::CreateApiFunction(
Handle<Map> map = Handle<Map>(result->initial_map());
+ // Mark as having external data object if needed
+ if (has_external_resource) {
+ map->set_has_external_resource(true);
+ }
+
// Mark as undetectable if needed.
if (obj->undetectable()) {
map->set_is_undetectable();
diff --git a/src/heap-inl.h b/src/heap-inl.h
index 4c55d63..bca57cb 100644
--- a/src/heap-inl.h
+++ b/src/heap-inl.h
@@ -222,21 +222,36 @@ MaybeObject* Heap::NumberFromUint32(uint32_t value) {
}
-void Heap::FinalizeExternalString(String* string) {
- ASSERT(string->IsExternalString());
- v8::String::ExternalStringResourceBase** resource_addr =
- reinterpret_cast<v8::String::ExternalStringResourceBase**>(
- reinterpret_cast<byte*>(string) +
- ExternalString::kResourceOffset -
- kHeapObjectTag);
-
- // Dispose of the C++ object if it has not already been disposed.
- if (*resource_addr != NULL) {
- (*resource_addr)->Dispose();
+void Heap::FinalizeExternalString(HeapObject* string) {
+ ASSERT(string->IsExternalString() || string->map()->has_external_resource());
+
+ if (string->IsExternalString()) {
+ v8::String::ExternalStringResourceBase** resource_addr =
+ reinterpret_cast<v8::String::ExternalStringResourceBase**>(
+ reinterpret_cast<byte*>(string) +
+ ExternalString::kResourceOffset -
+ kHeapObjectTag);
+
+ // Dispose of the C++ object if it has not already been disposed.
+ if (*resource_addr != NULL) {
+ (*resource_addr)->Dispose();
+ }
+
+ // Clear the resource pointer in the string.
+ *resource_addr = NULL;
+ } else {
+ JSObject *object = JSObject::cast(string);
+ Object *value = object->GetExternalResourceObject();
+ v8::Object::ExternalResource *resource = 0;
+ if (value->IsSmi()) {
+ resource = reinterpret_cast<v8::Object::ExternalResource*>(Internals::GetExternalPointerFromSmi(value));
+ } else if (value->IsForeign()) {
+ resource = reinterpret_cast<v8::Object::ExternalResource*>(Foreign::cast(value)->address());
+ }
+ if (resource) {
+ resource->Dispose();
+ }
}
-
- // Clear the resource pointer in the string.
- *resource_addr = NULL;
}
@@ -555,6 +570,16 @@ void ExternalStringTable::AddString(String* string) {
}
+void ExternalStringTable::AddObject(HeapObject* object) {
+ ASSERT(object->map()->has_external_resource());
+ if (heap_->InNewSpace(object)) {
+ new_space_strings_.Add(object);
+ } else {
+ old_space_strings_.Add(object);
+ }
+}
+
+
void ExternalStringTable::Iterate(ObjectVisitor* v) {
if (!new_space_strings_.is_empty()) {
Object** start = &new_space_strings_[0];
@@ -583,14 +608,14 @@ void ExternalStringTable::Verify() {
}
-void ExternalStringTable::AddOldString(String* string) {
- ASSERT(string->IsExternalString());
- ASSERT(!heap_->InNewSpace(string));
- old_space_strings_.Add(string);
+void ExternalStringTable::AddOldObject(HeapObject* object) {
+ ASSERT(object->IsExternalString() || object->map()->has_external_resource());
+ ASSERT(!heap_->InNewSpace(object));
+ old_space_strings_.Add(object);
}
-void ExternalStringTable::ShrinkNewStrings(int position) {
+void ExternalStringTable::ShrinkNewObjects(int position) {
new_space_strings_.Rewind(position);
if (FLAG_verify_heap) {
Verify();
diff --git a/src/heap.cc b/src/heap.cc
index d287ead..53a0f27 100644
--- a/src/heap.cc
+++ b/src/heap.cc
@@ -1099,18 +1099,18 @@ void Heap::Scavenge() {
}
-String* Heap::UpdateNewSpaceReferenceInExternalStringTableEntry(Heap* heap,
- Object** p) {
+HeapObject* Heap::UpdateNewSpaceReferenceInExternalStringTableEntry(Heap* heap,
+ Object** p) {
MapWord first_word = HeapObject::cast(*p)->map_word();
if (!first_word.IsForwardingAddress()) {
// Unreachable external string can be finalized.
- heap->FinalizeExternalString(String::cast(*p));
+ heap->FinalizeExternalString(HeapObject::cast(*p));
return NULL;
}
// String is still reachable.
- return String::cast(first_word.ToForwardingAddress());
+ return HeapObject::cast(first_word.ToForwardingAddress());
}
@@ -1128,11 +1128,11 @@ void Heap::UpdateNewSpaceReferencesInExternalStringTable(
for (Object** p = start; p < end; ++p) {
ASSERT(InFromSpace(*p));
- String* target = updater_func(this, p);
+ HeapObject* target = updater_func(this, p);
if (target == NULL) continue;
- ASSERT(target->IsExternalString());
+ ASSERT(target->IsExternalString() || target->map()->has_external_resource());
if (InNewSpace(target)) {
// String is still in new space. Update the table entry.
@@ -1140,12 +1140,12 @@ void Heap::UpdateNewSpaceReferencesInExternalStringTable(
++last;
} else {
// String got promoted. Move it to the old string list.
- external_string_table_.AddOldString(target);
+ external_string_table_.AddOldObject(target);
}
}
ASSERT(last <= end);
- external_string_table_.ShrinkNewStrings(static_cast<int>(last - start));
+ external_string_table_.ShrinkNewObjects(static_cast<int>(last - start));
}
@@ -6367,6 +6367,19 @@ void ExternalStringTable::CleanUp() {
void ExternalStringTable::TearDown() {
+ for (int i = 0; i < new_space_strings_.length(); ++i) {
+ if (new_space_strings_[i] == heap_->raw_unchecked_null_value()) continue;
+ HeapObject *object = HeapObject::cast(new_space_strings_[i]);
+ if (!object->IsExternalString())
+ heap_->FinalizeExternalString(object);
+ }
+ for (int i = 0; i < old_space_strings_.length(); ++i) {
+ if (old_space_strings_[i] == heap_->raw_unchecked_null_value()) continue;
+ HeapObject *object = HeapObject::cast(old_space_strings_[i]);
+ if (!object->IsExternalString())
+ heap_->FinalizeExternalString(object);
+ }
+
new_space_strings_.Free();
old_space_strings_.Free();
}
diff --git a/src/heap.h b/src/heap.h
index 7c0b0ea..5e90964 100644
--- a/src/heap.h
+++ b/src/heap.h
@@ -245,8 +245,8 @@ class Isolate;
class WeakObjectRetainer;
-typedef String* (*ExternalStringTableUpdaterCallback)(Heap* heap,
- Object** pointer);
+typedef HeapObject* (*ExternalStringTableUpdaterCallback)(Heap* heap,
+ Object** pointer);
class StoreBufferRebuilder {
public:
@@ -331,10 +331,14 @@ typedef void (*ScavengingCallback)(Map* map,
// External strings table is a place where all external strings are
// registered. We need to keep track of such strings to properly
// finalize them.
+// The ExternalStringTable can contain both strings and objects with
+// external resources. It was not renamed to make the patch simpler.
class ExternalStringTable {
public:
// Registers an external string.
inline void AddString(String* string);
+ // Registers an external object.
+ inline void AddObject(HeapObject* string);
inline void Iterate(ObjectVisitor* v);
@@ -352,10 +356,10 @@ class ExternalStringTable {
inline void Verify();
- inline void AddOldString(String* string);
+ inline void AddOldObject(HeapObject* string);
// Notifies the table that only a prefix of the new list is valid.
- inline void ShrinkNewStrings(int position);
+ inline void ShrinkNewObjects(int position);
// To speed up scavenge collections new space string are kept
// separate from old space strings.
@@ -851,7 +855,7 @@ class Heap {
// Finalizes an external string by deleting the associated external
// data and clearing the resource pointer.
- inline void FinalizeExternalString(String* string);
+ inline void FinalizeExternalString(HeapObject* string);
// Allocates an uninitialized object. The memory is non-executable if the
// hardware and OS allow.
@@ -1656,7 +1660,7 @@ class Heap {
// Performs a minor collection in new generation.
void Scavenge();
- static String* UpdateNewSpaceReferenceInExternalStringTableEntry(
+ static HeapObject* UpdateNewSpaceReferenceInExternalStringTableEntry(
Heap* heap,
Object** pointer);
diff --git a/src/mark-compact.cc b/src/mark-compact.cc
index b41b033..bf0aab8 100644
--- a/src/mark-compact.cc
+++ b/src/mark-compact.cc
@@ -1513,8 +1513,9 @@ class SymbolTableCleaner : public ObjectVisitor {
// Since no objects have yet been moved we can safely access the map of
// the object.
- if (o->IsExternalString()) {
- heap_->FinalizeExternalString(String::cast(*p));
+ if (o->IsExternalString() ||
+ (o->IsHeapObject() && HeapObject::cast(o)->map()->has_external_resource())) {
+ heap_->FinalizeExternalString(HeapObject::cast(*p));
}
// Set the entry to null_value (as deleted).
*p = heap_->null_value();
@@ -2487,15 +2488,15 @@ static void UpdatePointer(HeapObject** p, HeapObject* object) {
}
-static String* UpdateReferenceInExternalStringTableEntry(Heap* heap,
- Object** p) {
+static HeapObject* UpdateReferenceInExternalStringTableEntry(Heap* heap,
+ Object** p) {
MapWord map_word = HeapObject::cast(*p)->map_word();
if (map_word.IsForwardingAddress()) {
- return String::cast(map_word.ToForwardingAddress());
+ return HeapObject::cast(map_word.ToForwardingAddress());
}
- return String::cast(*p);
+ return HeapObject::cast(*p);
}
diff --git a/src/objects-inl.h b/src/objects-inl.h
index 1cfea84..6a80c9c 100644
--- a/src/objects-inl.h
+++ b/src/objects-inl.h
@@ -1343,7 +1343,7 @@ int JSObject::GetInternalFieldCount() {
// Make sure to adjust for the number of in-object properties. These
// properties do contribute to the size, but are not internal fields.
return ((Size() - GetHeaderSize()) >> kPointerSizeLog2) -
- map()->inobject_properties();
+ map()->inobject_properties() - (map()->has_external_resource()?1:0);
}
@@ -1373,6 +1373,23 @@ void JSObject::SetInternalField(int index, Object* value) {
}
+void JSObject::SetExternalResourceObject(Object *value) {
+ ASSERT(map()->has_external_resource());
+ int offset = GetHeaderSize() + kPointerSize * GetInternalFieldCount();
+ WRITE_FIELD(this, offset, value);
+ WRITE_BARRIER(GetHeap(), this, offset, value);
+}
+
+
+Object *JSObject::GetExternalResourceObject() {
+ if (map()->has_external_resource()) {
+ return READ_FIELD(this, GetHeaderSize() + kPointerSize * GetInternalFieldCount());
+ } else {
+ return GetHeap()->undefined_value();
+ }
+}
+
+
// Access fast-case object properties at index. The use of these routines
// is needed to correctly distinguish between properties stored in-object and
// properties stored in the properties array.
@@ -2755,6 +2772,20 @@ bool Map::is_shared() {
return ((1 << kIsShared) & bit_field3()) != 0;
}
+void Map::set_has_external_resource(bool value) {
+ if (value) {
+ set_bit_field(bit_field() | (1 << kHasExternalResource));
+ } else {
+ set_bit_field(bit_field() & ~(1 << kHasExternalResource));
+ }
+}
+
+bool Map::has_external_resource()
+{
+ return ((1 << kHasExternalResource) & bit_field()) != 0;
+}
+
+
void Map::set_named_interceptor_is_fallback(bool value)
{
if (value) {
@@ -3301,6 +3332,8 @@ ACCESSORS(FunctionTemplateInfo, flag, Smi, kFlagOffset)
ACCESSORS(ObjectTemplateInfo, constructor, Object, kConstructorOffset)
ACCESSORS(ObjectTemplateInfo, internal_field_count, Object,
kInternalFieldCountOffset)
+ACCESSORS(ObjectTemplateInfo, has_external_resource, Object,
+ kHasExternalResourceOffset)
ACCESSORS(SignatureInfo, receiver, Object, kReceiverOffset)
ACCESSORS(SignatureInfo, args, Object, kArgsOffset)
diff --git a/src/objects.h b/src/objects.h
index ed40061..c38d461 100644
--- a/src/objects.h
+++ b/src/objects.h
@@ -1760,6 +1760,9 @@ class JSObject: public JSReceiver {
inline Object* GetInternalField(int index);
inline void SetInternalField(int index, Object* value);
+ inline void SetExternalResourceObject(Object *);
+ inline Object *GetExternalResourceObject();
+
// The following lookup functions skip interceptors.
void LocalLookupRealNamedProperty(String* name, LookupResult* result);
void LookupRealNamedProperty(String* name, LookupResult* result);
@@ -4171,11 +4174,11 @@ class Map: public HeapObject {
// Tells whether the instance has a call-as-function handler.
inline void set_has_instance_call_handler() {
- set_bit_field(bit_field() | (1 << kHasInstanceCallHandler));
+ set_bit_field3(bit_field3() | (1 << kHasInstanceCallHandler));
}
inline bool has_instance_call_handler() {
- return ((1 << kHasInstanceCallHandler) & bit_field()) != 0;
+ return ((1 << kHasInstanceCallHandler) & bit_field3()) != 0;
}
inline void set_is_extensible(bool value);
@@ -4247,6 +4250,11 @@ class Map: public HeapObject {
inline void set_named_interceptor_is_fallback(bool value);
inline bool named_interceptor_is_fallback();
+ // Tells whether the instance has the space for an external resource
+ // object
+ inline void set_has_external_resource(bool value);
+ inline bool has_external_resource();
+
// [prototype]: implicit prototype object.
DECL_ACCESSORS(prototype, Object)
@@ -4487,7 +4495,7 @@ class Map: public HeapObject {
static const int kHasNamedInterceptor = 3;
static const int kHasIndexedInterceptor = 4;
static const int kIsUndetectable = 5;
- static const int kHasInstanceCallHandler = 6;
+ static const int kHasExternalResource = 6;
static const int kIsAccessCheckNeeded = 7;
// Bit positions for bit field 2
@@ -4512,6 +4520,7 @@ class Map: public HeapObject {
// Bit positions for bit field 3
static const int kIsShared = 0;
static const int kNamedInterceptorIsFallback = 1;
+ static const int kHasInstanceCallHandler = 2;
// Layout of the default cache. It holds alternating name and code objects.
static const int kCodeCacheEntrySize = 2;
@@ -7539,6 +7548,7 @@ class ObjectTemplateInfo: public TemplateInfo {
public:
DECL_ACCESSORS(constructor, Object)
DECL_ACCESSORS(internal_field_count, Object)
+ DECL_ACCESSORS(has_external_resource, Object)
static inline ObjectTemplateInfo* cast(Object* obj);
@@ -7555,7 +7565,8 @@ class ObjectTemplateInfo: public TemplateInfo {
static const int kConstructorOffset = TemplateInfo::kHeaderSize;
static const int kInternalFieldCountOffset =
kConstructorOffset + kPointerSize;
- static const int kSize = kInternalFieldCountOffset + kPointerSize;
+ static const int kHasExternalResourceOffset = kInternalFieldCountOffset + kPointerSize;
+ static const int kSize = kHasExternalResourceOffset + kPointerSize;
};
--
1.7.4.1

File diff suppressed because it is too large Load Diff

View File

@ -1,48 +0,0 @@
From 2081f6baaab81d60564680de600b4dcf03de6cd4 Mon Sep 17 00:00:00 2001
From: Aaron Kennedy <aaron.kennedy@nokia.com>
Date: Fri, 14 Oct 2011 17:03:06 +1000
Subject: [PATCH 05/13] Allow access to the calling script data
---
include/v8.h | 1 +
src/api.cc | 12 ++++++++++++
2 files changed, 13 insertions(+), 0 deletions(-)
diff --git a/include/v8.h b/include/v8.h
index 193e2fe..c094d08 100644
--- a/include/v8.h
+++ b/include/v8.h
@@ -3517,6 +3517,7 @@ class V8EXPORT Context {
*/
static Local<Context> GetCalling();
static Local<Object> GetCallingQmlGlobal();
+ static Local<Value> GetCallingScriptData();
/**
* Sets the security token for the context. To access an object in
diff --git a/src/api.cc b/src/api.cc
index 2d3d97a..54df40d 100644
--- a/src/api.cc
+++ b/src/api.cc
@@ -4370,6 +4370,18 @@ v8::Local<v8::Object> Context::GetCallingQmlGlobal() {
}
}
+v8::Local<v8::Value> Context::GetCallingScriptData()
+{
+ i::Isolate* isolate = i::Isolate::Current();
+ if (IsDeadCheck(isolate, "v8::Context::GetCallingScriptData()")) {
+ return Local<Object>();
+ }
+
+ i::JavaScriptFrameIterator it;
+ if (it.done()) return Local<Object>();
+ i::Handle<i::Script> script(i::Script::cast(i::JSFunction::cast(it.frame()->function())->shared()->script()));
+ return Utils::ToLocal(i::Handle<i::Object>(script->data()));
+}
v8::Local<v8::Object> Context::Global() {
if (IsDeadCheck(i::Isolate::Current(), "v8::Context::Global()")) {
--
1.7.4.1

View File

@ -1,548 +0,0 @@
From d2d3c19a32e2f7a5586811bb10ea75a79a11f52f Mon Sep 17 00:00:00 2001
From: Aaron Kennedy <aaron.kennedy@nokia.com>
Date: Thu, 27 Oct 2011 13:40:00 +0100
Subject: [PATCH 06/13] Add custom object compare callback
A global custom object comparison callback can be set with:
V8::SetUserObjectComparisonCallbackFunction()
When two JSObjects are compared (== or !=), if either one has
the MarkAsUseUserObjectComparison() bit set, the custom comparison
callback is invoked to do the actual comparison.
This is useful when you have "value" objects that you want to
compare as equal, even though they are actually different JS object
instances.
---
include/v8.h | 13 +++++++++++++
src/api.cc | 22 ++++++++++++++++++++++
src/arm/code-stubs-arm.cc | 43 +++++++++++++++++++++++++++++++++++++++++--
src/factory.cc | 8 ++++++++
src/ia32/code-stubs-ia32.cc | 39 +++++++++++++++++++++++++++++++++++++++
src/isolate.cc | 7 +++++++
src/isolate.h | 8 ++++++++
src/objects-inl.h | 21 ++++++++++++++++++---
src/objects.cc | 8 ++++----
src/objects.h | 12 ++++++++++--
src/runtime.cc | 23 +++++++++++++++++++++++
src/runtime.h | 1 +
src/x64/code-stubs-x64.cc | 37 +++++++++++++++++++++++++++++++++++++
13 files changed, 231 insertions(+), 11 deletions(-)
diff --git a/include/v8.h b/include/v8.h
index c094d08..6baf2b2 100644
--- a/include/v8.h
+++ b/include/v8.h
@@ -2501,6 +2501,12 @@ class V8EXPORT ObjectTemplate : public Template {
bool HasExternalResource();
void SetHasExternalResource(bool value);
+ /**
+ * Mark object instances of the template as using the user object
+ * comparison callback.
+ */
+ void MarkAsUseUserObjectComparison();
+
private:
ObjectTemplate();
static Local<ObjectTemplate> New(Handle<FunctionTemplate> constructor);
@@ -2720,6 +2726,10 @@ typedef void (*FailedAccessCheckCallback)(Local<Object> target,
AccessType type,
Local<Value> data);
+// --- User Object Comparisoa nCallback ---
+typedef bool (*UserObjectComparisonCallback)(Local<Object> lhs,
+ Local<Object> rhs);
+
// --- AllowCodeGenerationFromStrings callbacks ---
/**
@@ -3046,6 +3056,9 @@ class V8EXPORT V8 {
/** Callback function for reporting failed access checks.*/
static void SetFailedAccessCheckCallbackFunction(FailedAccessCheckCallback);
+ /** Callback for user object comparisons */
+ static void SetUserObjectComparisonCallbackFunction(UserObjectComparisonCallback);
+
/**
* Enables the host application to receive a notification before a
* garbage collection. Allocations are not allowed in the
diff --git a/src/api.cc b/src/api.cc
index 54df40d..974d702 100644
--- a/src/api.cc
+++ b/src/api.cc
@@ -1464,6 +1464,17 @@ void ObjectTemplate::SetHasExternalResource(bool value)
}
+void ObjectTemplate::MarkAsUseUserObjectComparison()
+{
+ i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate();
+ if (IsDeadCheck(isolate, "v8::ObjectTemplate::MarkAsUseUserObjectComparison()")) {
+ return;
+ }
+ ENTER_V8(isolate);
+ EnsureConstructor(this);
+ Utils::OpenHandle(this)->set_use_user_object_comparison(i::Smi::FromInt(1));
+}
+
// --- S c r i p t D a t a ---
@@ -5113,6 +5124,17 @@ void V8::SetFailedAccessCheckCallbackFunction(
isolate->SetFailedAccessCheckCallback(callback);
}
+
+void V8::SetUserObjectComparisonCallbackFunction(
+ UserObjectComparisonCallback callback) {
+ i::Isolate* isolate = i::Isolate::Current();
+ if (IsDeadCheck(isolate, "v8::V8::SetUserObjectComparisonCallbackFunction()")) {
+ return;
+ }
+ isolate->SetUserObjectComparisonCallback(callback);
+}
+
+
void V8::AddObjectGroup(Persistent<Value>* objects,
size_t length,
RetainedObjectInfo* info) {
diff --git a/src/arm/code-stubs-arm.cc b/src/arm/code-stubs-arm.cc
index f5be938..1e1aebd 100644
--- a/src/arm/code-stubs-arm.cc
+++ b/src/arm/code-stubs-arm.cc
@@ -1569,6 +1569,37 @@ void CompareStub::Generate(MacroAssembler* masm) {
// NOTICE! This code is only reached after a smi-fast-case check, so
// it is certain that at least one operand isn't a smi.
+ {
+ Label not_user_equal, user_equal;
+ __ and_(r2, r1, Operand(r0));
+ __ tst(r2, Operand(kSmiTagMask));
+ __ b(eq, &not_user_equal);
+
+ __ CompareObjectType(r0, r2, r4, JS_OBJECT_TYPE);
+ __ b(ne, &not_user_equal);
+
+ __ CompareObjectType(r1, r3, r4, JS_OBJECT_TYPE);
+ __ b(ne, &not_user_equal);
+
+ __ ldrb(r2, FieldMemOperand(r2, Map::kBitField2Offset));
+ __ and_(r2, r2, Operand(1 << Map::kUseUserObjectComparison));
+ __ cmp(r2, Operand(1 << Map::kUseUserObjectComparison));
+ __ b(eq, &user_equal);
+
+ __ ldrb(r3, FieldMemOperand(r3, Map::kBitField2Offset));
+ __ and_(r3, r3, Operand(1 << Map::kUseUserObjectComparison));
+ __ cmp(r3, Operand(1 << Map::kUseUserObjectComparison));
+ __ b(ne, &not_user_equal);
+
+ __ bind(&user_equal);
+
+ __ Push(r0, r1);
+ __ TailCallRuntime(Runtime::kUserObjectEquals, 2, 1);
+
+ __ bind(&not_user_equal);
+ }
+
+
// Handle the case where the objects are identical. Either returns the answer
// or goes to slow. Only falls through if the objects were not identical.
EmitIdenticalObjectComparison(masm, &slow, cc_, never_nan_nan_);
@@ -6615,10 +6646,18 @@ void ICCompareStub::GenerateObjects(MacroAssembler* masm) {
__ and_(r2, r1, Operand(r0));
__ JumpIfSmi(r2, &miss);
- __ CompareObjectType(r0, r2, r2, JS_OBJECT_TYPE);
+ __ CompareObjectType(r0, r2, r3, JS_OBJECT_TYPE);
__ b(ne, &miss);
- __ CompareObjectType(r1, r2, r2, JS_OBJECT_TYPE);
+ __ ldrb(r2, FieldMemOperand(r2, Map::kBitField2Offset));
+ __ and_(r2, r2, Operand(1 << Map::kUseUserObjectComparison));
+ __ cmp(r2, Operand(1 << Map::kUseUserObjectComparison));
+ __ b(eq, &miss);
+ __ CompareObjectType(r1, r2, r3, JS_OBJECT_TYPE);
__ b(ne, &miss);
+ __ ldrb(r2, FieldMemOperand(r2, Map::kBitField2Offset));
+ __ and_(r2, r2, Operand(1 << Map::kUseUserObjectComparison));
+ __ cmp(r2, Operand(1 << Map::kUseUserObjectComparison));
+ __ b(eq, &miss);
ASSERT(GetCondition() == eq);
__ sub(r0, r0, Operand(r1));
diff --git a/src/factory.cc b/src/factory.cc
index 8c96944..76ca69d 100644
--- a/src/factory.cc
+++ b/src/factory.cc
@@ -1153,6 +1153,7 @@ Handle<JSFunction> Factory::CreateApiFunction(
int internal_field_count = 0;
bool has_external_resource = false;
+ bool use_user_object_comparison = false;
if (!obj->instance_template()->IsUndefined()) {
Handle<ObjectTemplateInfo> instance_template =
@@ -1162,6 +1163,8 @@ Handle<JSFunction> Factory::CreateApiFunction(
Smi::cast(instance_template->internal_field_count())->value();
has_external_resource =
!instance_template->has_external_resource()->IsUndefined();
+ use_user_object_comparison =
+ !instance_template->use_user_object_comparison()->IsUndefined();
}
int instance_size = kPointerSize * internal_field_count;
@@ -1206,6 +1209,11 @@ Handle<JSFunction> Factory::CreateApiFunction(
map->set_has_external_resource(true);
}
+ // Mark as using user object comparison if needed
+ if (use_user_object_comparison) {
+ map->set_use_user_object_comparison(true);
+ }
+
// Mark as undetectable if needed.
if (obj->undetectable()) {
map->set_is_undetectable();
diff --git a/src/ia32/code-stubs-ia32.cc b/src/ia32/code-stubs-ia32.cc
index 8a94a06..e73753e 100644
--- a/src/ia32/code-stubs-ia32.cc
+++ b/src/ia32/code-stubs-ia32.cc
@@ -4020,6 +4020,39 @@ void CompareStub::Generate(MacroAssembler* masm) {
// NOTICE! This code is only reached after a smi-fast-case check, so
// it is certain that at least one operand isn't a smi.
+ {
+ Label not_user_equal, user_equal;
+ __ test(eax, Immediate(kSmiTagMask));
+ __ j(zero, &not_user_equal);
+ __ test(edx, Immediate(kSmiTagMask));
+ __ j(zero, &not_user_equal);
+
+ __ CmpObjectType(eax, JS_OBJECT_TYPE, ebx);
+ __ j(not_equal, &not_user_equal);
+
+ __ CmpObjectType(edx, JS_OBJECT_TYPE, ecx);
+ __ j(not_equal, &not_user_equal);
+
+ __ test_b(FieldOperand(ebx, Map::kBitField2Offset),
+ 1 << Map::kUseUserObjectComparison);
+ __ j(not_zero, &user_equal);
+ __ test_b(FieldOperand(ecx, Map::kBitField2Offset),
+ 1 << Map::kUseUserObjectComparison);
+ __ j(not_zero, &user_equal);
+
+ __ jmp(&not_user_equal);
+
+ __ bind(&user_equal);
+
+ __ pop(ebx); // Return address.
+ __ push(eax);
+ __ push(edx);
+ __ push(ebx);
+ __ TailCallRuntime(Runtime::kUserObjectEquals, 2, 1);
+
+ __ bind(&not_user_equal);
+ }
+
// Identical objects can be compared fast, but there are some tricky cases
// for NaN and undefined.
{
@@ -6497,8 +6530,14 @@ void ICCompareStub::GenerateObjects(MacroAssembler* masm) {
__ CmpObjectType(eax, JS_OBJECT_TYPE, ecx);
__ j(not_equal, &miss, Label::kNear);
+ __ test_b(FieldOperand(ecx, Map::kBitField2Offset),
+ 1 << Map::kUseUserObjectComparison);
+ __ j(not_zero, &miss, Label::kNear);
__ CmpObjectType(edx, JS_OBJECT_TYPE, ecx);
__ j(not_equal, &miss, Label::kNear);
+ __ test_b(FieldOperand(ecx, Map::kBitField2Offset),
+ 1 << Map::kUseUserObjectComparison);
+ __ j(not_zero, &miss, Label::kNear);
ASSERT(GetCondition() == equal);
__ sub(eax, edx);
diff --git a/src/isolate.cc b/src/isolate.cc
index a073af9..36c1dfd 100644
--- a/src/isolate.cc
+++ b/src/isolate.cc
@@ -96,6 +96,7 @@ void ThreadLocalTop::InitializeInternal() {
thread_id_ = ThreadId::Invalid();
external_caught_exception_ = false;
failed_access_check_callback_ = NULL;
+ user_object_comparison_callback_ = NULL;
save_context_ = NULL;
catcher_ = NULL;
top_lookup_result_ = NULL;
@@ -729,6 +730,12 @@ void Isolate::SetFailedAccessCheckCallback(
thread_local_top()->failed_access_check_callback_ = callback;
}
+
+void Isolate::SetUserObjectComparisonCallback(
+ v8::UserObjectComparisonCallback callback) {
+ thread_local_top()->user_object_comparison_callback_ = callback;
+}
+
void Isolate::ReportFailedAccessCheck(JSObject* receiver, v8::AccessType type) {
if (!thread_local_top()->failed_access_check_callback_) return;
diff --git a/src/isolate.h b/src/isolate.h
index 5453bf2..9919e83 100644
--- a/src/isolate.h
+++ b/src/isolate.h
@@ -258,6 +258,9 @@ class ThreadLocalTop BASE_EMBEDDED {
// Head of the list of live LookupResults.
LookupResult* top_lookup_result_;
+ // Call back function for user object comparisons
+ v8::UserObjectComparisonCallback user_object_comparison_callback_;
+
// Whether out of memory exceptions should be ignored.
bool ignore_out_of_memory_;
@@ -703,6 +706,11 @@ class Isolate {
void SetFailedAccessCheckCallback(v8::FailedAccessCheckCallback callback);
void ReportFailedAccessCheck(JSObject* receiver, v8::AccessType type);
+ void SetUserObjectComparisonCallback(v8::UserObjectComparisonCallback callback);
+ inline v8::UserObjectComparisonCallback UserObjectComparisonCallback() {
+ return thread_local_top()->user_object_comparison_callback_;
+ }
+
// Exception throwing support. The caller should use the result
// of Throw() as its return value.
Failure* Throw(Object* exception, MessageLocation* location = NULL);
diff --git a/src/objects-inl.h b/src/objects-inl.h
index 2e83fb7..13d7591 100644
--- a/src/objects-inl.h
+++ b/src/objects-inl.h
@@ -2749,14 +2749,14 @@ bool Map::is_extensible() {
void Map::set_attached_to_shared_function_info(bool value) {
if (value) {
- set_bit_field2(bit_field2() | (1 << kAttachedToSharedFunctionInfo));
+ set_bit_field3(bit_field3() | (1 << kAttachedToSharedFunctionInfo));
} else {
- set_bit_field2(bit_field2() & ~(1 << kAttachedToSharedFunctionInfo));
+ set_bit_field3(bit_field3() & ~(1 << kAttachedToSharedFunctionInfo));
}
}
bool Map::attached_to_shared_function_info() {
- return ((1 << kAttachedToSharedFunctionInfo) & bit_field2()) != 0;
+ return ((1 << kAttachedToSharedFunctionInfo) & bit_field3()) != 0;
}
@@ -2786,6 +2786,19 @@ bool Map::has_external_resource()
}
+void Map::set_use_user_object_comparison(bool value) {
+ if (value) {
+ set_bit_field2(bit_field2() | (1 << kUseUserObjectComparison));
+ } else {
+ set_bit_field2(bit_field2() & ~(1 << kUseUserObjectComparison));
+ }
+}
+
+bool Map::use_user_object_comparison() {
+ return ((1 << kUseUserObjectComparison) & bit_field2()) != 0;
+}
+
+
void Map::set_named_interceptor_is_fallback(bool value)
{
if (value) {
@@ -3334,6 +3347,8 @@ ACCESSORS(ObjectTemplateInfo, internal_field_count, Object,
kInternalFieldCountOffset)
ACCESSORS(ObjectTemplateInfo, has_external_resource, Object,
kHasExternalResourceOffset)
+ACCESSORS(ObjectTemplateInfo, use_user_object_comparison, Object,
+ kUseUserObjectComparisonOffset)
ACCESSORS(SignatureInfo, receiver, Object, kReceiverOffset)
ACCESSORS(SignatureInfo, args, Object, kArgsOffset)
diff --git a/src/objects.cc b/src/objects.cc
index f5b6bee..6a4eff9 100644
--- a/src/objects.cc
+++ b/src/objects.cc
@@ -7686,8 +7686,8 @@ void SharedFunctionInfo::DetachInitialMap() {
Map* map = reinterpret_cast<Map*>(initial_map());
// Make the map remember to restore the link if it survives the GC.
- map->set_bit_field2(
- map->bit_field2() | (1 << Map::kAttachedToSharedFunctionInfo));
+ map->set_bit_field3(
+ map->bit_field3() | (1 << Map::kAttachedToSharedFunctionInfo));
// Undo state changes made by StartInobjectTracking (except the
// construction_count). This way if the initial map does not survive the GC
@@ -7707,8 +7707,8 @@ void SharedFunctionInfo::DetachInitialMap() {
// Called from GC, hence reinterpret_cast and unchecked accessors.
void SharedFunctionInfo::AttachInitialMap(Map* map) {
- map->set_bit_field2(
- map->bit_field2() & ~(1 << Map::kAttachedToSharedFunctionInfo));
+ map->set_bit_field3(
+ map->bit_field3() & ~(1 << Map::kAttachedToSharedFunctionInfo));
// Resume inobject slack tracking.
set_initial_map(map);
diff --git a/src/objects.h b/src/objects.h
index b71eaac..3137437 100644
--- a/src/objects.h
+++ b/src/objects.h
@@ -4258,6 +4258,11 @@ class Map: public HeapObject {
inline void set_has_external_resource(bool value);
inline bool has_external_resource();
+ // Tells whether the user object comparison callback should be used for
+ // comparisons involving this object
+ inline void set_use_user_object_comparison(bool value);
+ inline bool use_user_object_comparison();
+
// [prototype]: implicit prototype object.
DECL_ACCESSORS(prototype, Object)
@@ -4505,7 +4510,7 @@ class Map: public HeapObject {
static const int kIsExtensible = 0;
static const int kFunctionWithPrototype = 1;
static const int kStringWrapperSafeForDefaultValueOf = 2;
- static const int kAttachedToSharedFunctionInfo = 3;
+ static const int kUseUserObjectComparison = 3;
// No bits can be used after kElementsKindFirstBit, they are all reserved for
// storing ElementKind.
static const int kElementsKindShift = 4;
@@ -4524,6 +4529,7 @@ class Map: public HeapObject {
static const int kIsShared = 0;
static const int kNamedInterceptorIsFallback = 1;
static const int kHasInstanceCallHandler = 2;
+ static const int kAttachedToSharedFunctionInfo = 3;
// Layout of the default cache. It holds alternating name and code objects.
static const int kCodeCacheEntrySize = 2;
@@ -7556,6 +7562,7 @@ class ObjectTemplateInfo: public TemplateInfo {
DECL_ACCESSORS(constructor, Object)
DECL_ACCESSORS(internal_field_count, Object)
DECL_ACCESSORS(has_external_resource, Object)
+ DECL_ACCESSORS(use_user_object_comparison, Object)
static inline ObjectTemplateInfo* cast(Object* obj);
@@ -7573,7 +7580,8 @@ class ObjectTemplateInfo: public TemplateInfo {
static const int kInternalFieldCountOffset =
kConstructorOffset + kPointerSize;
static const int kHasExternalResourceOffset = kInternalFieldCountOffset + kPointerSize;
- static const int kSize = kHasExternalResourceOffset + kPointerSize;
+ static const int kUseUserObjectComparisonOffset = kHasExternalResourceOffset + kPointerSize;
+ static const int kSize = kUseUserObjectComparisonOffset + kPointerSize;
};
diff --git a/src/runtime.cc b/src/runtime.cc
index b64e66b..8010169 100644
--- a/src/runtime.cc
+++ b/src/runtime.cc
@@ -7095,6 +7095,29 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_StringEquals) {
}
+RUNTIME_FUNCTION(MaybeObject*, Runtime_UserObjectEquals) {
+ NoHandleAllocation ha;
+ ASSERT(args.length() == 2);
+
+ CONVERT_CHECKED(JSObject, lhs, args[1]);
+ CONVERT_CHECKED(JSObject, rhs, args[0]);
+
+ bool result;
+
+ v8::UserObjectComparisonCallback callback = isolate->UserObjectComparisonCallback();
+ if (callback) {
+ HandleScope scope(isolate);
+ Handle<JSObject> lhs_handle(lhs);
+ Handle<JSObject> rhs_handle(rhs);
+ result = callback(v8::Utils::ToLocal(lhs_handle), v8::Utils::ToLocal(rhs_handle));
+ } else {
+ result = (lhs == rhs);
+ }
+
+ return Smi::FromInt(result?0:1);
+}
+
+
RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberCompare) {
NoHandleAllocation ha;
ASSERT(args.length() == 3);
diff --git a/src/runtime.h b/src/runtime.h
index aada06d..cd36da9 100644
--- a/src/runtime.h
+++ b/src/runtime.h
@@ -157,6 +157,7 @@ namespace internal {
/* Comparisons */ \
F(NumberEquals, 2, 1) \
F(StringEquals, 2, 1) \
+ F(UserObjectEquals, 2, 1) \
\
F(NumberCompare, 3, 1) \
F(SmiLexicographicCompare, 2, 1) \
diff --git a/src/x64/code-stubs-x64.cc b/src/x64/code-stubs-x64.cc
index f30221f..ff8337f 100644
--- a/src/x64/code-stubs-x64.cc
+++ b/src/x64/code-stubs-x64.cc
@@ -3088,6 +3088,37 @@ void CompareStub::Generate(MacroAssembler* masm) {
// NOTICE! This code is only reached after a smi-fast-case check, so
// it is certain that at least one operand isn't a smi.
+ {
+ Label not_user_equal, user_equal;
+ __ JumpIfSmi(rax, &not_user_equal);
+ __ JumpIfSmi(rdx, &not_user_equal);
+
+ __ CmpObjectType(rax, JS_OBJECT_TYPE, rbx);
+ __ j(not_equal, &not_user_equal);
+
+ __ CmpObjectType(rdx, JS_OBJECT_TYPE, rcx);
+ __ j(not_equal, &not_user_equal);
+
+ __ testb(FieldOperand(rbx, Map::kBitField2Offset),
+ Immediate(1 << Map::kUseUserObjectComparison));
+ __ j(not_zero, &user_equal);
+ __ testb(FieldOperand(rcx, Map::kBitField2Offset),
+ Immediate(1 << Map::kUseUserObjectComparison));
+ __ j(not_zero, &user_equal);
+
+ __ jmp(&not_user_equal);
+
+ __ bind(&user_equal);
+
+ __ pop(rbx); // Return address.
+ __ push(rax);
+ __ push(rdx);
+ __ push(rbx);
+ __ TailCallRuntime(Runtime::kUserObjectEquals, 2, 1);
+
+ __ bind(&not_user_equal);
+ }
+
// Two identical objects are equal unless they are both NaN or undefined.
{
Label not_identical;
@@ -5421,8 +5452,14 @@ void ICCompareStub::GenerateObjects(MacroAssembler* masm) {
__ CmpObjectType(rax, JS_OBJECT_TYPE, rcx);
__ j(not_equal, &miss, Label::kNear);
+ __ testb(FieldOperand(rcx, Map::kBitField2Offset),
+ Immediate(1 << Map::kUseUserObjectComparison));
+ __ j(not_zero, &miss, Label::kNear);
__ CmpObjectType(rdx, JS_OBJECT_TYPE, rcx);
__ j(not_equal, &miss, Label::kNear);
+ __ testb(FieldOperand(rcx, Map::kBitField2Offset),
+ Immediate(1 << Map::kUseUserObjectComparison));
+ __ j(not_zero, &miss, Label::kNear);
ASSERT(GetCondition() == equal);
__ subq(rax, rdx);
--
1.7.4.1

View File

@ -1,46 +0,0 @@
From 1ecd533461383671ea465b37f2cad84a0aad3d52 Mon Sep 17 00:00:00 2001
From: Aaron Kennedy <aaron.kennedy@nokia.com>
Date: Fri, 9 Sep 2011 14:16:12 +1000
Subject: [PATCH 07/13] Allow a script to be flagged as "native"
Native scripts do not appear in backtraces, or in the source and
line number when exceptions are thrown from within them. This is
useful to be able to write code in JavaScript instead of C++ and
still have it appear sensibly to the user.
---
include/v8.h | 5 +++--
src/compiler.cc | 2 +-
2 files changed, 4 insertions(+), 3 deletions(-)
diff --git a/include/v8.h b/include/v8.h
index 6baf2b2..229ddbd 100644
--- a/include/v8.h
+++ b/include/v8.h
@@ -588,8 +588,9 @@ class ScriptOrigin {
class V8EXPORT Script {
public:
enum CompileFlags {
- Default = 0x00,
- QmlMode = 0x01
+ Default = 0x00,
+ QmlMode = 0x01,
+ NativeMode = 0x02
};
/**
diff --git a/src/compiler.cc b/src/compiler.cc
index 4902e72..cabca74 100644
--- a/src/compiler.cc
+++ b/src/compiler.cc
@@ -499,7 +499,7 @@ Handle<SharedFunctionInfo> Compiler::Compile(Handle<String> source,
// Create a script object describing the script to be compiled.
Handle<Script> script = FACTORY->NewScript(source);
- if (natives == NATIVES_CODE) {
+ if (natives == NATIVES_CODE || compile_flags & v8::Script::NativeMode) {
script->set_type(Smi::FromInt(Script::TYPE_NATIVE));
}
if (!script_name.is_null()) {
--
1.7.4.1

View File

@ -1,63 +0,0 @@
From c7850561fcdf333a5b80a50623c7d4507757b315 Mon Sep 17 00:00:00 2001
From: Jedrzej Nowacki <jedrzej.nowacki@nokia.com>
Date: Tue, 7 Dec 2010 11:56:42 +0100
Subject: [PATCH 08/13] QtScript/V8: Add new v8 api to check if a value is an error.
New function v8::Value::IsError was created.
This API is experimental and added only for the purposes of our
research.
---
include/v8.h | 5 +++++
src/api.cc | 6 ++++++
src/heap.h | 1 +
3 files changed, 12 insertions(+), 0 deletions(-)
diff --git a/include/v8.h b/include/v8.h
index 229ddbd..d995e54 100644
--- a/include/v8.h
+++ b/include/v8.h
@@ -967,6 +967,11 @@ class Value : public Data {
*/
V8EXPORT bool IsRegExp() const;
+ /**
+ * Returns true if this value is an Error.
+ */
+ V8EXPORT bool IsError() const;
+
V8EXPORT Local<Boolean> ToBoolean() const;
V8EXPORT Local<Number> ToNumber() const;
V8EXPORT Local<String> ToString() const;
diff --git a/src/api.cc b/src/api.cc
index 974d702..a16ef65 100644
--- a/src/api.cc
+++ b/src/api.cc
@@ -2316,6 +2316,12 @@ bool Value::IsRegExp() const {
return obj->IsJSRegExp();
}
+bool Value::IsError() const {
+ if (IsDeadCheck(i::Isolate::Current(), "v8::Value::IsError()")) return false;
+ i::Handle<i::Object> obj = Utils::OpenHandle(this);
+ return obj->HasSpecificClassOf(HEAP->Error_symbol());
+}
+
Local<String> Value::ToString() const {
i::Handle<i::Object> obj = Utils::OpenHandle(this);
diff --git a/src/heap.h b/src/heap.h
index 5e90964..6166cde 100644
--- a/src/heap.h
+++ b/src/heap.h
@@ -190,6 +190,7 @@ inline Heap* _inline_get_heap_();
V(string_symbol, "string") \
V(String_symbol, "String") \
V(Date_symbol, "Date") \
+ V(Error_symbol, "Error") \
V(this_symbol, "this") \
V(to_string_symbol, "toString") \
V(char_at_symbol, "CharAt") \
--
1.7.4.1

View File

@ -1,51 +0,0 @@
From 4a9995fd141e40df2493dc2ef12d91f0a946629a Mon Sep 17 00:00:00 2001
From: Kent Hansen <kent.hansen@nokia.com>
Date: Fri, 2 Sep 2011 12:03:09 +0200
Subject: [PATCH 09/13] Fix deprecated Python code
Needed to make the scripts run on Python 3, which is the
default python interpreter on some newer distros.
Patch from http://code.google.com/p/v8/issues/detail?id=1391
---
tools/js2c.py | 4 ++--
tools/jsmin.py | 2 +-
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/tools/js2c.py b/tools/js2c.py
index a2ea8ea..fe6a72e 100644
--- a/tools/js2c.py
+++ b/tools/js2c.py
@@ -194,14 +194,14 @@ def ReadMacros(lines):
macro_match = MACRO_PATTERN.match(line)
if macro_match:
name = macro_match.group(1)
- args = map(string.strip, macro_match.group(2).split(','))
+ args = args = [match.strip() for match in macro_match.group(2).split(',')]
body = macro_match.group(3).strip()
macros.append((re.compile("\\b%s\\(" % name), TextMacro(args, body)))
else:
python_match = PYTHON_MACRO_PATTERN.match(line)
if python_match:
name = python_match.group(1)
- args = map(string.strip, python_match.group(2).split(','))
+ args = [match.strip() for match in python_match.group(2).split(',')]
body = python_match.group(3).strip()
fun = eval("lambda " + ",".join(args) + ': ' + body)
macros.append((re.compile("\\b%s\\(" % name), PythonMacro(args, fun)))
diff --git a/tools/jsmin.py b/tools/jsmin.py
index 646bf14..395441b 100644
--- a/tools/jsmin.py
+++ b/tools/jsmin.py
@@ -154,7 +154,7 @@ class JavaScriptMinifier(object):
return var_name
while True:
identifier_first_char = self.identifier_counter % 52
- identifier_second_char = self.identifier_counter / 52
+ identifier_second_char = self.identifier_counter // 52
new_identifier = self.CharFromNumber(identifier_first_char)
if identifier_second_char != 0:
new_identifier = (
--
1.7.4.1

View File

@ -1,15 +0,0 @@
From 8498e4b40d8355aa51dd8f4641dd1fdd4704e7bd Mon Sep 17 00:00:00 2001
From: Aaron Kennedy <aaron.kennedy@nokia.com>
Date: Thu, 25 Aug 2011 11:09:58 +1000
Subject: [PATCH 10/13] Remove execute flag from v8-debug.h
---
0 files changed, 0 insertions(+), 0 deletions(-)
mode change 100755 => 100644 include/v8-debug.h
diff --git a/include/v8-debug.h b/include/v8-debug.h
old mode 100755
new mode 100644
--
1.7.4.1

View File

@ -1,46 +0,0 @@
From 6643bd52181d51570bb1f9806dd06ff3b66c4251 Mon Sep 17 00:00:00 2001
From: Aaron Kennedy <aaron.kennedy@nokia.com>
Date: Fri, 27 May 2011 13:04:15 +1000
Subject: [PATCH 11/13] Fix warnings
---
include/v8.h | 16 ++++++++--------
1 files changed, 8 insertions(+), 8 deletions(-)
diff --git a/include/v8.h b/include/v8.h
index d995e54..a7b5c8a 100644
--- a/include/v8.h
+++ b/include/v8.h
@@ -2579,7 +2579,7 @@ class V8EXPORT Extension { // NOLINT
int source_length = -1);
virtual ~Extension() { }
virtual v8::Handle<v8::FunctionTemplate>
- GetNativeFunction(v8::Handle<v8::String> name) {
+ GetNativeFunction(v8::Handle<v8::String>) {
return v8::Handle<v8::FunctionTemplate>();
}
@@ -3946,13 +3946,13 @@ class Internals {
return *reinterpret_cast<T*>(addr);
}
- static inline bool CanCastToHeapObject(void* o) { return false; }
- static inline bool CanCastToHeapObject(Context* o) { return true; }
- static inline bool CanCastToHeapObject(String* o) { return true; }
- static inline bool CanCastToHeapObject(Object* o) { return true; }
- static inline bool CanCastToHeapObject(Message* o) { return true; }
- static inline bool CanCastToHeapObject(StackTrace* o) { return true; }
- static inline bool CanCastToHeapObject(StackFrame* o) { return true; }
+ static inline bool CanCastToHeapObject(void*) { return false; }
+ static inline bool CanCastToHeapObject(Context*) { return true; }
+ static inline bool CanCastToHeapObject(String*) { return true; }
+ static inline bool CanCastToHeapObject(Object*) { return true; }
+ static inline bool CanCastToHeapObject(Message*) { return true; }
+ static inline bool CanCastToHeapObject(StackTrace*) { return true; }
+ static inline bool CanCastToHeapObject(StackFrame*) { return true; }
};
} // namespace internal
--
1.7.4.1

View File

@ -1,147 +0,0 @@
From f37d702159f3e606610b74fb2b56ece63d510a6e Mon Sep 17 00:00:00 2001
From: Kai Koehne <kai.koehne@nokia.com>
Date: Thu, 10 Nov 2011 16:00:37 +0100
Subject: [PATCH 12/13] Add flag to avoid breakpoint relocation
Add a flag that prevents v8 from relocating breakpoints across
line boundaries.
---
src/debug.cc | 29 +++++++++++++++++++---
src/flag-definitions.h | 1 +
test/cctest/test-debug.cc | 59 +++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 85 insertions(+), 4 deletions(-)
diff --git a/src/debug.cc b/src/debug.cc
index dc9f297..d32574b 100644
--- a/src/debug.cc
+++ b/src/debug.cc
@@ -1131,6 +1131,17 @@ Handle<DebugInfo> Debug::GetDebugInfo(Handle<SharedFunctionInfo> shared) {
return Handle<DebugInfo>(DebugInfo::cast(shared->debug_info()));
}
+static bool ContainsLineBreak(String *string, int from, int to)
+{
+ ASSERT(from >= 0);
+ ASSERT(from <= to);
+ const int end = (string->length() < to) ? string->length() : to;
+ for (int pos = from; pos < end; ++pos) {
+ if (string->Get(pos) == '\n')
+ return true;
+ }
+ return false;
+}
void Debug::SetBreakPoint(Handle<SharedFunctionInfo> shared,
Handle<Object> break_point_object,
@@ -1151,12 +1162,22 @@ void Debug::SetBreakPoint(Handle<SharedFunctionInfo> shared,
// Find the break point and change it.
BreakLocationIterator it(debug_info, SOURCE_BREAK_LOCATIONS);
it.FindBreakLocationFromPosition(*source_position);
- it.SetBreakPoint(break_point_object);
- *source_position = it.position();
+ bool acceptBreak = true;
+ if (!FLAG_breakpoint_relocation) {
+ if (String *sourceStr = String::cast(shared->GetSourceCode())) {
+ acceptBreak = !ContainsLineBreak(sourceStr, *source_position, it.position());
+ }
+ }
+
+ if (acceptBreak) {
+ it.SetBreakPoint(break_point_object);
- // At least one active break point now.
- ASSERT(debug_info->GetBreakPointCount() > 0);
+ *source_position = it.position();
+
+ // At least one active break point now.
+ ASSERT(debug_info->GetBreakPointCount() > 0);
+ }
}
diff --git a/src/flag-definitions.h b/src/flag-definitions.h
index ee6ef01..fe64a96 100644
--- a/src/flag-definitions.h
+++ b/src/flag-definitions.h
@@ -233,6 +233,7 @@ DEFINE_bool(trace_debug_json, false, "trace debugging JSON request/response")
DEFINE_bool(debugger_auto_break, true,
"automatically set the debug break flag when debugger commands are "
"in the queue")
+DEFINE_bool(breakpoint_relocation, true, "relocate breakpoints to the next executable line")
DEFINE_bool(enable_liveedit, true, "enable liveedit experimental feature")
// execution.cc
diff --git a/test/cctest/test-debug.cc b/test/cctest/test-debug.cc
index cf723ba..7e51c34 100644
--- a/test/cctest/test-debug.cc
+++ b/test/cctest/test-debug.cc
@@ -2305,6 +2305,65 @@ TEST(ScriptBreakPointTopLevelCrash) {
CheckDebuggerUnloaded();
}
+// Test that breakpoint_relocation flag is honored
+TEST(ScriptBreakPointNoRelocation) {
+ i::FLAG_breakpoint_relocation = false;
+
+ v8::HandleScope scope;
+ DebugLocalContext env;
+ env.ExposeDebug();
+
+ // Create a function for checking the function when hitting a break point.
+ frame_function_name = CompileFunction(&env,
+ frame_function_name_source,
+ "frame_function_name");
+
+ v8::Debug::SetDebugEventListener(DebugEventBreakPointHitCount,
+ v8::Undefined());
+
+ v8::Local<v8::String> script1 = v8::String::New(
+ "a = 0 // line 0\n"
+ " // line 1\n"
+ " // line 2\n"
+ " // line 3\n"
+ "function f() { // line 4\n"
+ " return 0; // line 5\n"
+ "} // line 6");
+
+ // Set the script break point on the empty line
+ SetScriptBreakPointByNameFromJS("test.html", 2, -1);
+
+ // Compile the script and call the function.
+ v8::ScriptOrigin origin(v8::String::New("test.html"), v8::Integer::New(0));
+ v8::Script::Compile(script1, &origin)->Run();
+ v8::Local<v8::Function> f
+ = v8::Local<v8::Function>::Cast(env->Global()->Get(v8::String::New("f")));
+ f->Call(env->Global(), 0, NULL);
+
+ // Check that a break point was not hit
+ CHECK_EQ(0, break_point_hit_count);
+
+ v8::Local<v8::String> script2 = v8::String::New(
+ "a = 0 // line 0\n"
+ "function g() { // line 1\n"
+ " return 0; // line 2\n"
+ "} // line 3\n"
+ "function f() { // line 4\n"
+ " return 0; // line 5\n"
+ "} // line 6");
+
+ // Compile the script and call the new function
+ v8::Script::Compile(script2, &origin)->Run();
+ v8::Local<v8::Function> g
+ = v8::Local<v8::Function>::Cast(env->Global()->Get(v8::String::New("g")));
+ g->Call(env->Global(), 0, NULL);
+
+ // Check that a break point was not hit
+ CHECK_EQ(1, break_point_hit_count);
+
+ v8::Debug::SetDebugEventListener(NULL);
+ CheckDebuggerUnloaded();
+}
// Test that it is possible to remove the last break point for a function
// inside the break handling of that break point.
--
1.7.4.1

View File

@ -1,68 +0,0 @@
From f02e75f4f2fdffcac78317dff38c6ca6e679cf5c Mon Sep 17 00:00:00 2001
From: Aurindam Jana <aurindam.jana@nokia.com>
Date: Tue, 13 Dec 2011 13:43:23 +0100
Subject: [PATCH 13/13] Update ScriptBreakPoints for ScriptRegExp
Update breakpoints of type ScriptRegExpwhen a new script
is compiled. Solves Issue 1853
(http://code.google.com/p/v8/issues/detail?id=1853)
Reviewed-by: aaron.kennedy@nokia.com
---
src/debug-debugger.js | 3 ++-
test/mjsunit/debug-setbreakpoint.js | 12 ++++++++++--
2 files changed, 12 insertions(+), 3 deletions(-)
diff --git a/src/debug-debugger.js b/src/debug-debugger.js
index d254ee5..6f80a8b 100644
--- a/src/debug-debugger.js
+++ b/src/debug-debugger.js
@@ -477,7 +477,8 @@ ScriptBreakPoint.prototype.clear = function () {
// break points set in this script.
function UpdateScriptBreakPoints(script) {
for (var i = 0; i < script_break_points.length; i++) {
- if (script_break_points[i].type() == Debug.ScriptBreakPointType.ScriptName &&
+ if ((script_break_points[i].type() == Debug.ScriptBreakPointType.ScriptName ||
+ script_break_points[i].type() == Debug.ScriptBreakPointType.ScriptRegExp) &&
script_break_points[i].matchesScript(script)) {
script_break_points[i].set(script);
}
diff --git a/test/mjsunit/debug-setbreakpoint.js b/test/mjsunit/debug-setbreakpoint.js
index 90dfcd1..03ba28e 100644
--- a/test/mjsunit/debug-setbreakpoint.js
+++ b/test/mjsunit/debug-setbreakpoint.js
@@ -49,14 +49,17 @@ function safeEval(code) {
}
}
-function testArguments(dcp, arguments, success, is_script) {
+function testArguments(dcp, arguments, success, is_script, is_script_reg_exp) {
var request = '{' + base_request + ',"arguments":' + arguments + '}'
var json_response = dcp.processDebugJSONRequest(request);
var response = safeEval(json_response);
if (success) {
assertTrue(response.success, request + ' -> ' + json_response);
if (is_script) {
- assertEquals('scriptName', response.body.type, request + ' -> ' + json_response);
+ if (is_script_reg_exp)
+ assertEquals('scriptRegExp', response.body.type, request + ' -> ' + json_response);
+ else
+ assertEquals('scriptName', response.body.type, request + ' -> ' + json_response);
} else {
assertEquals('scriptId', response.body.type, request + ' -> ' + json_response);
}
@@ -108,6 +111,11 @@ function listener(event, exec_state, event_data, data) {
testArguments(dcp, '{"type":"script","target":"test","line":1}', true, true);
testArguments(dcp, '{"type":"script","target":"test","column":1}', true, true);
+ testArguments(dcp, '{"type":"scriptRegExp","target":"test"}', true, true, true);
+ testArguments(dcp, '{"type":"scriptRegExp","target":"test"}', true, true, true);
+ testArguments(dcp, '{"type":"scriptRegExp","target":"test","line":1}', true, true, true);
+ testArguments(dcp, '{"type":"scriptRegExp","target":"test","column":1}', true, true, true);
+
testArguments(dcp, '{"type":"scriptId","target":' + f_script_id + ',"line":' + f_line + '}', true, false);
testArguments(dcp, '{"type":"scriptId","target":' + g_script_id + ',"line":' + g_line + '}', true, false);
testArguments(dcp, '{"type":"scriptId","target":' + h_script_id + ',"line":' + h_line + '}', true, false);
--
1.7.4.1

View File

@ -1 +0,0 @@
These patches apply cleanly against v8 at e123c9dfe54146f8bfca38841255f63a95a00a19

View File

@ -1,307 +0,0 @@
isEmpty(QT_ARCH) {
# We're most likely being parsed in a fromfile() call, in which case the
# QMake environment isn't complete. Load qt_config in an attempt to set
# the variables we need (QT_ARCH and CONFIG, in particular).
load(qt_config)
}
isEmpty(V8_TARGET_ARCH) {
# Detect target
equals(QT_ARCH, x86_64)|contains(CONFIG, x86_64):V8_TARGET_ARCH = x64
else:equals(QT_ARCH, "i386"): V8_TARGET_ARCH = ia32
else:equals(QT_ARCH, "mips"): V8_TARGET_ARCH = mips
else:equals(QT_ARCH, "arm"): V8_TARGET_ARCH = arm
else:equals(QMAKE_HOST.arch, armv7l): V8_TARGET_ARCH = arm
else:equals(QMAKE_HOST.arch, armv5tel): V8_TARGET_ARCH = arm
else:equals(QMAKE_HOST.arch, x86_64): V8_TARGET_ARCH = x64
else:equals(QMAKE_HOST.arch, x86): V8_TARGET_ARCH = ia32
else:equals(QMAKE_HOST.arch, i386): V8_TARGET_ARCH = ia32
else:equals(QMAKE_HOST.arch, i686): V8_TARGET_ARCH = ia32
else:error("Couldn't detect supported v8 architecture ($$QMAKE_HOST.arch/$$QT_ARCH). Currently supported architectures are: x64, x86 and arm")
}
include($$PWD/v8base.pri)
# In debug-and-release builds, generated sources must not go to the same
# directory, or they could clobber each other in highly parallelized builds
CONFIG(debug, debug|release):V8_GENERATED_SOURCES_DIR = generated-debug
else: V8_GENERATED_SOURCES_DIR = generated-release
# this maybe removed in future
DEFINES += ENABLE_DEBUGGER_SUPPORT
# this is needed by crankshaft ( http://code.google.com/p/v8/issues/detail?id=1271 )
DEFINES += ENABLE_VMSTATE_TRACKING ENABLE_LOGGING_AND_PROFILING
CONFIG(debug, debug|release) {
DEFINES += DEBUG V8_ENABLE_CHECKS OBJECT_PRINT ENABLE_DISASSEMBLER
} else {
DEFINES += NDEBUG
}
V8SRC = $$V8DIR/src
INCLUDEPATH += \
$$V8SRC
SOURCES += \
$$V8SRC/accessors.cc \
$$V8SRC/allocation.cc \
$$V8SRC/api.cc \
$$V8SRC/assembler.cc \
$$V8SRC/ast.cc \
$$V8SRC/atomicops_internals_x86_gcc.cc \
$$V8SRC/bignum.cc \
$$V8SRC/bignum-dtoa.cc \
$$V8SRC/bootstrapper.cc \
$$V8SRC/builtins.cc \
$$V8SRC/cached-powers.cc \
$$V8SRC/checks.cc \
$$V8SRC/circular-queue.cc \
$$V8SRC/code-stubs.cc \
$$V8SRC/codegen.cc \
$$V8SRC/compilation-cache.cc \
$$V8SRC/compiler.cc \
$$V8SRC/contexts.cc \
$$V8SRC/conversions.cc \
$$V8SRC/counters.cc \
$$V8SRC/cpu-profiler.cc \
$$V8SRC/data-flow.cc \
$$V8SRC/dateparser.cc \
$$V8SRC/debug-agent.cc \
$$V8SRC/debug.cc \
$$V8SRC/deoptimizer.cc \
$$V8SRC/disassembler.cc \
$$V8SRC/diy-fp.cc \
$$V8SRC/dtoa.cc \
$$V8SRC/elements.cc \
$$V8SRC/execution.cc \
$$V8SRC/factory.cc \
$$V8SRC/flags.cc \
$$V8SRC/frames.cc \
$$V8SRC/full-codegen.cc \
$$V8SRC/func-name-inferrer.cc \
$$V8SRC/gdb-jit.cc \
$$V8SRC/global-handles.cc \
$$V8SRC/fast-dtoa.cc \
$$V8SRC/fixed-dtoa.cc \
$$V8SRC/handles.cc \
$$V8SRC/hashmap.cc \
$$V8SRC/heap-profiler.cc \
$$V8SRC/heap.cc \
$$V8SRC/hydrogen.cc \
$$V8SRC/hydrogen-instructions.cc \
$$V8SRC/ic.cc \
$$V8SRC/incremental-marking.cc \
$$V8SRC/inspector.cc \
$$V8SRC/interpreter-irregexp.cc \
$$V8SRC/isolate.cc \
$$V8SRC/jsregexp.cc \
$$V8SRC/lithium-allocator.cc \
$$V8SRC/lithium.cc \
$$V8SRC/liveedit.cc \
$$V8SRC/liveobjectlist.cc \
$$V8SRC/log-utils.cc \
$$V8SRC/log.cc \
$$V8SRC/mark-compact.cc \
$$V8SRC/messages.cc \
$$V8SRC/objects.cc \
$$V8SRC/objects-printer.cc \
$$V8SRC/objects-visiting.cc \
$$V8SRC/parser.cc \
$$V8SRC/preparser.cc \
$$V8SRC/preparse-data.cc \
$$V8SRC/profile-generator.cc \
$$V8SRC/property.cc \
$$V8SRC/regexp-macro-assembler-irregexp.cc \
$$V8SRC/regexp-macro-assembler.cc \
$$V8SRC/regexp-stack.cc \
$$V8SRC/rewriter.cc \
$$V8SRC/runtime.cc \
$$V8SRC/runtime-profiler.cc \
$$V8SRC/safepoint-table.cc \
$$V8SRC/scanner.cc \
$$V8SRC/scanner-character-streams.cc \
$$V8SRC/scopeinfo.cc \
$$V8SRC/scopes.cc \
$$V8SRC/serialize.cc \
$$V8SRC/snapshot-common.cc \
$$V8SRC/spaces.cc \
$$V8SRC/string-search.cc \
$$V8SRC/string-stream.cc \
$$V8SRC/strtod.cc \
$$V8SRC/stub-cache.cc \
$$V8SRC/token.cc \
$$V8SRC/type-info.cc \
$$V8SRC/unicode.cc \
$$V8SRC/utils.cc \
$$V8SRC/v8-counters.cc \
$$V8SRC/v8.cc \
$$V8SRC/v8conversions.cc \
$$V8SRC/v8threads.cc \
$$V8SRC/v8utils.cc \
$$V8SRC/variables.cc \
$$V8SRC/version.cc \
$$V8SRC/store-buffer.cc \
$$V8SRC/zone.cc \
$$V8SRC/extensions/gc-extension.cc \
$$V8SRC/extensions/externalize-string-extension.cc
equals(V8_TARGET_ARCH, arm) {
DEFINES += V8_TARGET_ARCH_ARM
DEFINES += USE_EABI_HARDFLOAT=1 CAN_USE_VFP_INSTRUCTIONS
SOURCES += \
$$V8SRC/arm/builtins-arm.cc \
$$V8SRC/arm/code-stubs-arm.cc \
$$V8SRC/arm/codegen-arm.cc \
$$V8SRC/arm/constants-arm.cc \
$$V8SRC/arm/cpu-arm.cc \
$$V8SRC/arm/debug-arm.cc \
$$V8SRC/arm/deoptimizer-arm.cc \
$$V8SRC/arm/disasm-arm.cc \
$$V8SRC/arm/frames-arm.cc \
$$V8SRC/arm/full-codegen-arm.cc \
$$V8SRC/arm/ic-arm.cc \
$$V8SRC/arm/lithium-arm.cc \
$$V8SRC/arm/lithium-codegen-arm.cc \
$$V8SRC/arm/lithium-gap-resolver-arm.cc \
$$V8SRC/arm/macro-assembler-arm.cc \
$$V8SRC/arm/regexp-macro-assembler-arm.cc \
$$V8SRC/arm/stub-cache-arm.cc \
$$V8SRC/arm/assembler-arm.cc
} else:equals(V8_TARGET_ARCH, ia32) {
DEFINES += V8_TARGET_ARCH_IA32
SOURCES += \
$$V8SRC/ia32/assembler-ia32.cc \
$$V8SRC/ia32/builtins-ia32.cc \
$$V8SRC/ia32/code-stubs-ia32.cc \
$$V8SRC/ia32/codegen-ia32.cc \
$$V8SRC/ia32/cpu-ia32.cc \
$$V8SRC/ia32/debug-ia32.cc \
$$V8SRC/ia32/deoptimizer-ia32.cc \
$$V8SRC/ia32/disasm-ia32.cc \
$$V8SRC/ia32/frames-ia32.cc \
$$V8SRC/ia32/full-codegen-ia32.cc \
$$V8SRC/ia32/ic-ia32.cc \
$$V8SRC/ia32/lithium-codegen-ia32.cc \
$$V8SRC/ia32/lithium-gap-resolver-ia32.cc \
$$V8SRC/ia32/lithium-ia32.cc \
$$V8SRC/ia32/macro-assembler-ia32.cc \
$$V8SRC/ia32/regexp-macro-assembler-ia32.cc \
$$V8SRC/ia32/stub-cache-ia32.cc
} else:equals(V8_TARGET_ARCH, x64) {
# FIXME What about 32-bit Macs?
DEFINES += V8_TARGET_ARCH_X64
SOURCES += \
$$V8SRC/x64/assembler-x64.cc \
$$V8SRC/x64/builtins-x64.cc \
$$V8SRC/x64/code-stubs-x64.cc \
$$V8SRC/x64/codegen-x64.cc \
$$V8SRC/x64/cpu-x64.cc \
$$V8SRC/x64/debug-x64.cc \
$$V8SRC/x64/deoptimizer-x64.cc \
$$V8SRC/x64/disasm-x64.cc \
$$V8SRC/x64/frames-x64.cc \
$$V8SRC/x64/full-codegen-x64.cc \
$$V8SRC/x64/ic-x64.cc \
$$V8SRC/x64/lithium-codegen-x64.cc \
$$V8SRC/x64/lithium-gap-resolver-x64.cc \
$$V8SRC/x64/lithium-x64.cc \
$$V8SRC/x64/macro-assembler-x64.cc \
$$V8SRC/x64/regexp-macro-assembler-x64.cc \
$$V8SRC/x64/stub-cache-x64.cc
} else:equals(V8_TARGET_ARCH, mips) {
DEFINES += V8_TARGET_MIPS
SOURCES += \
$$V8SRC/mips/assembler-mips.cc \
$$V8SRC/mips/builtins-mips.cc \
$$V8SRC/mips/codegen-mips.cc \
$$V8SRC/mips/code-stubs-mips.cc \
$$V8SRC/mips/constants-mips.cc \
$$V8SRC/mips/cpu-mips.cc \
$$V8SRC/mips/debug-mips.cc \
$$V8SRC/mips/deoptimizer-mips.cc \
$$V8SRC/mips/disasm-mips.cc \
$$V8SRC/mips/frames-mips.cc \
$$V8SRC/mips/full-codegen-mips.cc \
$$V8SRC/mips/ic-mips.cc \
$$V8SRC/mips/macro-assembler-mips.cc \
$$V8SRC/mips/regexp-macro-assembler-mips.cc \
$$V8SRC/mips/simulator-mips.cc \
$$V8SRC/mips/stub-cache-mips.cc
}
#os:macos
macx {
SOURCES += \
$$V8SRC/platform-macos.cc \
$$V8SRC/platform-posix.cc
} else:freebsd-* {
SOURCES += \
$$V8SRC/platform-freebsd.cc \
$$V8SRC/platform-posix.cc
LIBS += -lexecinfo
} else:unix:!symbian {
SOURCES += \
$$V8SRC/platform-linux.cc \
$$V8SRC/platform-posix.cc
}
win32 {
SOURCES += \
$$V8SRC/platform-win32.cc \
$$V8SRC/win32-math.cc
LIBS += -lWs2_32 -lWinmm
win32-msvc*: QMAKE_CXXFLAGS += -wd4100 -wd 4291 -wd4351 -wd4355 -wd4800
win32-msvc*:arch_i386: DEFINES += _USE_32BIT_TIME_T
}
#mode:debug
CONFIG(debug) {
SOURCES += \
$$V8SRC/objects-debug.cc \
$$V8SRC/prettyprinter.cc \
$$V8SRC/regexp-macro-assembler-tracer.cc
}
V8_LIBRARY_FILES = \
$$V8SRC/runtime.js \
$$V8SRC/v8natives.js \
$$V8SRC/array.js \
$$V8SRC/string.js \
$$V8SRC/uri.js \
$$V8SRC/math.js \
$$V8SRC/messages.js \
$$V8SRC/apinatives.js \
$$V8SRC/date.js \
$$V8SRC/regexp.js \
$$V8SRC/json.js \
$$V8SRC/liveedit-debugger.js \
$$V8SRC/mirror-debugger.js \
$$V8SRC/debug-debugger.js
V8_EXPERIMENTAL_LIBRARY_FILES = \
$$V8SRC/proxy.js \
v8_js2c.commands = python $$V8DIR/tools/js2c.py $$V8_GENERATED_SOURCES_DIR/libraries.cpp CORE off
v8_js2c.commands += $$V8SRC/macros.py ${QMAKE_FILE_IN}
v8_js2c.output = $$V8_GENERATED_SOURCES_DIR/libraries.cpp
v8_js2c.input = V8_LIBRARY_FILES
v8_js2c.variable_out = SOURCES
v8_js2c.dependency_type = TYPE_C
v8_js2c.depends = $$V8DIR/tools/js2c.py $$V8SRC/macros.py
v8_js2c.CONFIG += combine
v8_js2c.name = generating[v8] ${QMAKE_FILE_IN}
silent:v8_js2c.commands = @echo generating[v8] ${QMAKE_FILE_IN} && $$v8_js2c.commands
v8_js2c_experimental.commands = python $$V8DIR/tools/js2c.py $$V8_GENERATED_SOURCES_DIR/experimental-libraries.cpp EXPERIMENTAL off
v8_js2c_experimental.commands += $$V8SRC/macros.py ${QMAKE_FILE_IN}
v8_js2c_experimental.output = $$V8_GENERATED_SOURCES_DIR/experimental-libraries.cpp
v8_js2c_experimental.input = V8_EXPERIMENTAL_LIBRARY_FILES
v8_js2c_experimental.variable_out = SOURCES
v8_js2c_experimental.dependency_type = TYPE_C
v8_js2c_experimental.depends = $$V8DIR/tools/js2c.py $$V8SRC/macros.py
v8_js2c_experimental.CONFIG += combine
v8_js2c_experimental.name = generating[v8] ${QMAKE_FILE_IN}
QMAKE_EXTRA_COMPILERS += v8_js2c v8_js2c_experimental

View File

@ -1,41 +0,0 @@
load(qt_module)
TARGET = QtV8
QPRO_PWD = $$PWD
QT =
CONFIG += module
MODULE_PRI = ../modules/qt_v8.pri
win32-msvc*|win32-icc:QMAKE_LFLAGS += /BASE:0x66000000
load(qt_module_config)
CONFIG += warn_off
# Remove includepaths that were added by qt_module_config.
# These cause compilation of V8 to fail because they appear before
# 3rdparty/v8/src; 3rdparty/v8/src/v8.h will then be "shadowed" by
# the public v8.h API header (they are not the same!).
INCLUDEPATH -= $$MODULE_PRIVATE_INCLUDES
INCLUDEPATH -= $$MODULE_PRIVATE_INCLUDES/$$TARGET
INCLUDEPATH -= $$MODULE_INCLUDES $$MODULE_INCLUDES/..
HEADERS += $$QT_SOURCE_TREE/src/v8/qtv8version.h
!contains(QT_CONFIG, static): DEFINES += V8_SHARED BUILDING_V8_SHARED
include(v8.pri)
contains(QT_CONFIG, v8snapshot) {
mkv8snapshot.commands = ../../bin/mkv8snapshot$$qtPlatformTargetSuffix() ${QMAKE_FILE_OUT}
DUMMY_FILE = v8.pro
mkv8snapshot.input = DUMMY_FILE
mkv8snapshot.output = $$V8_GENERATED_SOURCES_DIR/snapshot.cpp
mkv8snapshot.variable_out = SOURCES
mkv8snapshot.dependency_type = TYPE_C
mkv8snapshot.name = generating[v8] ${QMAKE_FILE_IN}
silent:mkv8snapshot.commands = @echo generating[v8] ${QMAKE_FILE_IN} && $$mkv8snapshot.commands
QMAKE_EXTRA_COMPILERS += mkv8snapshot
} else {
SOURCES += $$V8SRC/snapshot-empty.cc
}

View File

@ -1,24 +0,0 @@
V8DIR = $$(V8DIR)
isEmpty(V8DIR) {
V8DIR = $$PWD/../3rdparty/v8
!exists($$V8DIR/src):error("$$V8DIR/src does not exist! $$escape_expand(\\n)\
If you are building from git, please ensure you have the v8 submodule available, e.g. $$escape_expand(\\n\\n)\
git submodule update --init src/3rdparty/v8 $$escape_expand(\\n\\n)\
Alternatively, Qt may be configured with -no-v8 to disable v8.\
")
} else {
message(using external V8 from $$V8DIR)
}
*-g++*: {
QMAKE_CFLAGS_WARN_ON += -Wno-unused-parameter
QMAKE_CXXFLAGS_WARN_ON += -Wno-unused-parameter
# mksnapshot hangs if gcc 4.5 is used
# for reference look at http://code.google.com/p/v8/issues/detail?id=884
equals(QT_GCC_MAJOR_VERSION, 4): equals(QT_GCC_MINOR_VERSION, 5) {
message(because of a bug in gcc / v8 we need to add -fno-strict-aliasing)
QMAKE_CFLAGS += -fno-strict-aliasing
QMAKE_CXXFLAGS += -fno-strict-aliasing
}
}

View File

@ -4,7 +4,6 @@
"QtPrintSupport" => "$basedir/src/printsupport", "QtPrintSupport" => "$basedir/src/printsupport",
"QtOpenGL" => "$basedir/src/opengl", "QtOpenGL" => "$basedir/src/opengl",
"QtCore" => "$basedir/src/corelib", "QtCore" => "$basedir/src/corelib",
"QtV8" => "$basedir/src/v8",
"QtXml" => "$basedir/src/xml", "QtXml" => "$basedir/src/xml",
"QtSql" => "$basedir/src/sql", "QtSql" => "$basedir/src/sql",
"QtNetwork" => "$basedir/src/network", "QtNetwork" => "$basedir/src/network",
@ -13,10 +12,8 @@
"QtPlatformSupport" => "$basedir/src/platformsupport", "QtPlatformSupport" => "$basedir/src/platformsupport",
); );
%moduleheaders = ( # restrict the module headers to those found in relative path %moduleheaders = ( # restrict the module headers to those found in relative path
"QtV8" => "../3rdparty/v8/include",
); );
@allmoduleheadersprivate = ( @allmoduleheadersprivate = (
"QtV8"
); );
%classnames = ( %classnames = (
"qglobal.h" => "QtGlobal", "qglobal.h" => "QtGlobal",
@ -41,7 +38,6 @@
"qtopenvgversion.h" => "QtOpenVGVersion", "qtopenvgversion.h" => "QtOpenVGVersion",
"qtsqlversion.h" => "QtSqlVersion", "qtsqlversion.h" => "QtSqlVersion",
"qttestversion.h" => "QtTestVersion", "qttestversion.h" => "QtTestVersion",
"qtv8version.h" => "QtV8Version",
"qtxmlversion.h" => "QtXmlVersion", "qtxmlversion.h" => "QtXmlVersion",
); );
%mastercontent = ( %mastercontent = (
@ -63,7 +59,6 @@
"QtOpenGL" => "$basedir/src/modules/qt_opengl.pri", "QtOpenGL" => "$basedir/src/modules/qt_opengl.pri",
"QtSql" => "$basedir/src/modules/qt_sql.pri", "QtSql" => "$basedir/src/modules/qt_sql.pri",
"QtTest" => "$basedir/src/modules/qt_testlib.pri", "QtTest" => "$basedir/src/modules/qt_testlib.pri",
"QtV8" => "$basedir/src/modules/qt_v8.pri",
"QtXml" => "$basedir/src/modules/qt_xml.pri", "QtXml" => "$basedir/src/modules/qt_xml.pri",
"QtPlatformSupport" => "$basedir/src/modules/qt_platformsupport.pri", "QtPlatformSupport" => "$basedir/src/modules/qt_platformsupport.pri",
); );

View File

@ -9,7 +9,6 @@ SUBDIRS += \
sql \ sql \
testlib \ testlib \
tools \ tools \
v8 \
xml \ xml \
other \ other \
widgets \ widgets \
@ -17,7 +16,6 @@ SUBDIRS += \
cross_compile: SUBDIRS -= tools cross_compile: SUBDIRS -= tools
!contains(QT_CONFIG, opengl): SUBDIRS -= opengl !contains(QT_CONFIG, opengl): SUBDIRS -= opengl
!unix|embedded|!contains(QT_CONFIG, dbus): SUBDIRS -= dbus !unix|embedded|!contains(QT_CONFIG, dbus): SUBDIRS -= dbus
!contains(QT_CONFIG, v8): SUBDIRS -= v8
# disable 'make check' on Mac OS X for the following subdirs for the time being # disable 'make check' on Mac OS X for the following subdirs for the time being
mac { mac {

View File

@ -1,16 +0,0 @@
V8PATH = ../../../src/3rdparty/v8
V8LIBPATH = $(V8PATH)
V8INCPATH = $(V8PATH)/include
SOURCES = v8main.cpp v8test.cpp
release-m32:
g++ -o v8test_release_m32 -m32 -O2 -I$(V8INCPATH) $(SOURCES) -lpthread -L$(V8LIBPATH) -lv8
debug-m32:
g++ -o v8test_debug_m32 -m32 -g -I$(V8INCPATH) $(SOURCES) -lpthread -L$(V8LIBPATH) -lv8_g
release:
g++ -o v8test_release -O2 -I$(V8INCPATH) $(SOURCES) -lpthread -L$(V8LIBPATH) -lv8
debug:
g++ -o v8test_debug -g -I$(V8INCPATH) $(SOURCES) -lpthread -L$(V8LIBPATH) -lv8_g

View File

@ -1,13 +0,0 @@
The v8 tests are actually implemented in v8test.[h|cpp]. There are also QtTest
(tst_v8.cpp) and non-Qt (v8main.cpp) stubs provided to run these tests. This
is done to allow the tests to be run both in the Qt CI system, and manually
without a build of Qt. The latter is necessary to run them against more exotic
build of V8, like the ARM simulator.
To build the non-Qt version of the tests, first build a debug or release V8
library under src/3rdparty/v8 using scons, and then use the Makefile.nonqt
makefile selecting one of the following targets:
release: Build the tests with -O2 and link against libv8
debug: Build the tests with -g and link against libv8_g
release-m32: Build the tests with -O2 -m32 and link against libv8
debug-m32: Build the tests with -g -m32 and link against libv8_g

View File

@ -1,98 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this
** file. Please review the following information to ensure the GNU Lesser
** General Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU General
** Public License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of this
** file. Please review the following information to ensure the GNU General
** Public License version 3.0 requirements will be met:
** http://www.gnu.org/copyleft/gpl.html.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <qtest.h>
#include <private/v8.h>
#include "v8test.h"
using namespace v8;
class tst_v8 : public QObject
{
Q_OBJECT
public:
tst_v8() {}
private slots:
void initTestCase() {}
void cleanupTestCase() {}
void eval();
void evalwithinwith();
void userobjectcompare();
void externalteardown();
void globalcall();
};
void tst_v8::eval()
{
QVERIFY(v8test_eval());
}
void tst_v8::evalwithinwith()
{
QVERIFY(v8test_evalwithinwith());
}
void tst_v8::userobjectcompare()
{
QVERIFY(v8test_userobjectcompare());
}
void tst_v8::externalteardown()
{
QVERIFY(v8test_externalteardown());
}
void tst_v8::globalcall()
{
QVERIFY(v8test_globalcall());
}
int main(int argc, char *argv[])
{
V8::SetFlagsFromCommandLine(&argc, argv, true);
QCoreApplication app(argc, argv);
tst_v8 tc;
return QTest::qExec(&tc, argc, argv);
}
#include "tst_v8.moc"

View File

@ -1,10 +0,0 @@
CONFIG += testcase
TARGET = tst_v8
macx:CONFIG -= app_bundle
SOURCES += tst_v8.cpp v8test.cpp
HEADERS += v8test.h
CONFIG += parallel_test
QT = core v8-private testlib

View File

@ -1,66 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this
** file. Please review the following information to ensure the GNU Lesser
** General Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU General
** Public License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of this
** file. Please review the following information to ensure the GNU General
** Public License version 3.0 requirements will be met:
** http://www.gnu.org/copyleft/gpl.html.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "v8test.h"
#include <stdio.h>
#include <strings.h>
#define RUN_TEST(testname) { \
if (argc == 1 || 0 == ::strcmp(argv[1], # testname)) { \
if (!v8test_ ## testname()) \
printf ("Test %s FAILED\n", # testname); \
else \
printf ("Test %s PASS\n", # testname); \
} \
}
int main(int argc, char *argv[])
{
v8::V8::SetFlagsFromCommandLine(&argc, argv, true);
RUN_TEST(eval);
RUN_TEST(evalwithinwith);
RUN_TEST(userobjectcompare);
RUN_TEST(externalteardown);
RUN_TEST(globalcall);
return -1;
}

View File

@ -1,379 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this
** file. Please review the following information to ensure the GNU Lesser
** General Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU General
** Public License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of this
** file. Please review the following information to ensure the GNU General
** Public License version 3.0 requirements will be met:
** http://www.gnu.org/copyleft/gpl.html.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "v8test.h"
using namespace v8;
#define BEGINTEST() bool _testPassed = true;
#define ENDTEST() return _testPassed;
#define VERIFY(expr) { \
if (!(expr)) { \
fprintf(stderr, "FAIL: %s:%d %s\n", __FILE__, __LINE__, # expr); \
_testPassed = false; \
goto cleanup; \
} \
}
struct MyStringResource : public String::ExternalAsciiStringResource
{
static bool wasDestroyed;
virtual ~MyStringResource() { wasDestroyed = true; }
virtual const char* data() const { return "v8test"; }
virtual size_t length() const { return 6; }
};
bool MyStringResource::wasDestroyed = false;
struct MyResource : public Object::ExternalResource
{
static bool wasDestroyed;
virtual ~MyResource() { wasDestroyed = true; }
};
bool MyResource::wasDestroyed = false;
bool v8test_externalteardown()
{
BEGINTEST();
Isolate *isolate = v8::Isolate::New();
isolate->Enter();
{
HandleScope handle_scope;
Persistent<Context> context = Context::New();
Context::Scope context_scope(context);
String::NewExternal(new MyStringResource);
Local<FunctionTemplate> ft = FunctionTemplate::New();
ft->InstanceTemplate()->SetHasExternalResource(true);
Local<Object> obj = ft->GetFunction()->NewInstance();
obj->SetExternalResource(new MyResource);
context.Dispose();
}
// while (!v8::V8::IdleNotification()) ;
isolate->Exit();
isolate->Dispose();
// ExternalString resources aren't guaranteed to be freed by v8 at this
// point. Uncommenting the IdleNotification() line above helps.
// VERIFY(MyStringResource::wasDestroyed);
VERIFY(MyResource::wasDestroyed);
cleanup:
ENDTEST();
}
bool v8test_eval()
{
BEGINTEST();
HandleScope handle_scope;
Persistent<Context> context = Context::New();
Context::Scope context_scope(context);
Local<Object> qmlglobal = Object::New();
qmlglobal->Set(String::New("a"), Integer::New(1922));
Local<Script> script = Script::Compile(String::New("eval(\"a\")"), NULL, NULL,
Handle<String>(), Script::QmlMode);
TryCatch tc;
Local<Value> result = script->Run(qmlglobal);
VERIFY(!tc.HasCaught());
VERIFY(result->Int32Value() == 1922);
cleanup:
context.Dispose();
ENDTEST();
}
bool v8test_globalcall()
{
BEGINTEST();
HandleScope handle_scope;
Persistent<Context> context = Context::New();
Context::Scope context_scope(context);
Local<Object> qmlglobal = Object::New();
#define SOURCE "function func1() { return 1; }\n" \
"function func2() { var sum = 0; for (var ii = 0; ii < 10000000; ++ii) { sum += func1(); } return sum; }\n" \
"func2();"
Local<Script> script = Script::Compile(String::New(SOURCE), NULL, NULL,
Handle<String>(), Script::QmlMode);
Local<Value> result = script->Run(qmlglobal);
VERIFY(!result.IsEmpty());
VERIFY(result->IsInt32());
VERIFY(result->Int32Value() == 10000000);
#undef SOURCE
cleanup:
context.Dispose();
ENDTEST();
}
bool v8test_evalwithinwith()
{
BEGINTEST();
HandleScope handle_scope;
Persistent<Context> context = Context::New();
Context::Scope context_scope(context);
Local<Object> qmlglobal = Object::New();
qmlglobal->Set(String::New("a"), Integer::New(1922));
// There was a bug that the "eval" lookup would incorrectly resolve
// to the QML global object
qmlglobal->Set(String::New("eval"), Integer::New(1922));
#define SOURCE \
"(function() { " \
" var b = { c: 10 }; " \
" with (b) { " \
" return eval(\"a\"); " \
" } " \
"})"
Local<Script> script = Script::Compile(String::New(SOURCE), NULL, NULL,
Handle<String>(), Script::QmlMode);
#undef SOURCE
TryCatch tc;
Local<Value> result = script->Run(qmlglobal);
VERIFY(!tc.HasCaught());
VERIFY(result->IsFunction());
{
Local<Value> fresult = Handle<Function>::Cast(result)->Call(context->Global(), 0, 0);
VERIFY(!tc.HasCaught());
VERIFY(fresult->Int32Value() == 1922);
}
cleanup:
context.Dispose();
ENDTEST();
}
static int userObjectComparisonCalled = 0;
static bool userObjectComparisonReturn = false;
static Local<Object> expectedLhs;
static Local<Object> expectedRhs;
static bool expectedObjectsCompared = false;
#define SET_EXPECTED(lhs, rhs) { \
expectedObjectsCompared = false; \
expectedLhs = lhs; \
expectedRhs = rhs; \
}
static bool UserObjectComparison(Local<Object> lhs, Local<Object> rhs)
{
userObjectComparisonCalled++;
expectedObjectsCompared = (lhs == expectedLhs && rhs == expectedRhs);
return userObjectComparisonReturn;
}
inline bool runscript(const char *source) {
Local<Script> script = Script::Compile(String::New(source));
Local<Value> result = script->Run();
return result->BooleanValue();
}
bool v8test_userobjectcompare()
{
BEGINTEST();
HandleScope handle_scope;
Persistent<Context> context = Context::New();
Context::Scope context_scope(context);
V8::SetUserObjectComparisonCallbackFunction(UserObjectComparison);
Local<ObjectTemplate> ot = ObjectTemplate::New();
ot->MarkAsUseUserObjectComparison();
Local<Object> uoc1 = ot->NewInstance();
Local<Object> uoc2 = ot->NewInstance();
context->Global()->Set(String::New("uoc1a"), uoc1);
context->Global()->Set(String::New("uoc1b"), uoc1);
context->Global()->Set(String::New("uoc2"), uoc2);
Local<Object> obj1 = Object::New();
context->Global()->Set(String::New("obj1a"), obj1);
context->Global()->Set(String::New("obj1b"), obj1);
context->Global()->Set(String::New("obj2"), Object::New());
Local<String> string1 = String::New("Hello World");
context->Global()->Set(String::New("string1a"), string1);
context->Global()->Set(String::New("string1b"), string1);
context->Global()->Set(String::New("string2"), v8::String::New("Goodbye World"));
// XXX Opportunity for optimization - don't invoke user callback if objects are
// equal.
#if 0
userObjectComparisonCalled = 0; userObjectComparisonReturn = false;
VERIFY(true == runscript("uoc1a == uoc1b"));
VERIFY(userObjectComparisonCalled == 0);
#endif
// Comparing two uoc objects invokes uoc
userObjectComparisonCalled = 0;
userObjectComparisonReturn = false;
VERIFY(false == runscript("uoc1a == uoc2"));
VERIFY(userObjectComparisonCalled == 1);
VERIFY(false == runscript("uoc2 == uoc1a"));
VERIFY(userObjectComparisonCalled == 2);
userObjectComparisonReturn = true;
VERIFY(true == runscript("uoc1a == uoc2"));
VERIFY(userObjectComparisonCalled == 3);
VERIFY(true == runscript("uoc2 == uoc1a"));
VERIFY(userObjectComparisonCalled == 4);
// != on two uoc object invokes uoc
userObjectComparisonCalled = 0;
userObjectComparisonReturn = false;
VERIFY(true == runscript("uoc1a != uoc2"));
VERIFY(userObjectComparisonCalled == 1);
VERIFY(true == runscript("uoc2 != uoc1a"));
VERIFY(userObjectComparisonCalled == 2);
userObjectComparisonReturn = true;
VERIFY(false == runscript("uoc1a != uoc2"));
VERIFY(userObjectComparisonCalled == 3);
VERIFY(false == runscript("uoc2 != uoc1a"));
VERIFY(userObjectComparisonCalled == 4);
// Comparison against a non-object doesn't invoke uoc
userObjectComparisonCalled = 0;
userObjectComparisonReturn = false;
VERIFY(false == runscript("uoc1a == string1a"));
VERIFY(userObjectComparisonCalled == 0);
VERIFY(false == runscript("string1a == uoc1a"));
VERIFY(userObjectComparisonCalled == 0);
VERIFY(false == runscript("2 == uoc1a"));
VERIFY(userObjectComparisonCalled == 0);
VERIFY(true == runscript("uoc1a != string1a"));
VERIFY(userObjectComparisonCalled == 0);
VERIFY(true == runscript("string1a != uoc1a"));
VERIFY(userObjectComparisonCalled == 0);
VERIFY(true == runscript("2 != uoc1a"));
VERIFY(userObjectComparisonCalled == 0);
// Comparison against a non-uoc-object still invokes uoc
userObjectComparisonCalled = 0;
userObjectComparisonReturn = false;
VERIFY(false == runscript("uoc1a == obj1a"));
VERIFY(userObjectComparisonCalled == 1);
VERIFY(false == runscript("obj1a == uoc1a"));
VERIFY(userObjectComparisonCalled == 2);
userObjectComparisonReturn = true;
VERIFY(true == runscript("uoc1a == obj1a"));
VERIFY(userObjectComparisonCalled == 3);
VERIFY(true == runscript("obj1a == uoc1a"));
VERIFY(userObjectComparisonCalled == 4);
// != comparison against a non-uoc-object still invokes uoc
userObjectComparisonCalled = 0;
userObjectComparisonReturn = false;
VERIFY(true == runscript("uoc1a != obj1a"));
VERIFY(userObjectComparisonCalled == 1);
VERIFY(true == runscript("obj1a != uoc1a"));
VERIFY(userObjectComparisonCalled == 2);
userObjectComparisonReturn = true;
VERIFY(false == runscript("uoc1a != obj1a"));
VERIFY(userObjectComparisonCalled == 3);
VERIFY(false == runscript("obj1a != uoc1a"));
VERIFY(userObjectComparisonCalled == 4);
// Comparing two non-uoc objects does not invoke uoc
userObjectComparisonCalled = 0;
userObjectComparisonReturn = false;
VERIFY(true == runscript("obj1a == obj1a"));
VERIFY(true == runscript("obj1a == obj1b"));
VERIFY(false == runscript("obj1a == obj2"));
VERIFY(false == runscript("obj1a == string1a"));
VERIFY(true == runscript("string1a == string1a"));
VERIFY(true == runscript("string1a == string1b"));
VERIFY(false == runscript("string1a == string2"));
VERIFY(userObjectComparisonCalled == 0);
// Correct lhs and rhs passed to uoc
userObjectComparisonCalled = 0;
userObjectComparisonReturn = false;
SET_EXPECTED(uoc1, uoc2);
VERIFY(false == runscript("uoc1a == uoc2"));
VERIFY(true == expectedObjectsCompared);
SET_EXPECTED(uoc2, uoc1);
VERIFY(false == runscript("uoc2 == uoc1a"));
VERIFY(true == expectedObjectsCompared);
SET_EXPECTED(uoc1, uoc2);
VERIFY(true == runscript("uoc1a != uoc2"));
VERIFY(true == expectedObjectsCompared);
SET_EXPECTED(uoc2, uoc1);
VERIFY(true == runscript("uoc2 != uoc1a"));
VERIFY(true == expectedObjectsCompared);
SET_EXPECTED(uoc1, obj1);
VERIFY(false == runscript("uoc1a == obj1a"));
VERIFY(true == expectedObjectsCompared);
SET_EXPECTED(obj1, uoc1);
VERIFY(false == runscript("obj1a == uoc1a"));
VERIFY(true == expectedObjectsCompared);
cleanup:
V8::SetUserObjectComparisonCallbackFunction(0);
context.Dispose();
ENDTEST();
}

View File

@ -1,58 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this
** file. Please review the following information to ensure the GNU Lesser
** General Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU General
** Public License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of this
** file. Please review the following information to ensure the GNU General
** Public License version 3.0 requirements will be met:
** http://www.gnu.org/copyleft/gpl.html.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef V8TEST_H
#define V8TEST_H
#ifdef QT_CORE_LIB
#include <private/v8.h>
#else
#include <v8.h>
#endif
bool v8test_eval();
bool v8test_evalwithinwith();
bool v8test_userobjectcompare();
bool v8test_externalteardown();
bool v8test_globalcall();
#endif // V8TEST_H