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:
parent
159098719b
commit
51d634ce2e
3
.gitignore
vendored
3
.gitignore
vendored
@ -128,13 +128,10 @@ src/openvg/qtopenvgversion.h
|
||||
src/sql/qtsqlversion.h
|
||||
src/testlib/qttestversion.h
|
||||
src/xml/qtxmlversion.h
|
||||
src/v8/qtv8version.h
|
||||
src/platformsupport/qtplatformsupportversion.h
|
||||
src/printsupport/qtprintsupportversion.h
|
||||
src/widgets/qtwidgetsversion.h
|
||||
|
||||
src/v8/generated-debug/
|
||||
|
||||
# Test generated files
|
||||
QObject.log
|
||||
tst_*
|
||||
|
3
.gitmodules
vendored
3
.gitmodules
vendored
@ -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
src/3rdparty/v8
vendored
@ -1 +0,0 @@
|
||||
Subproject commit a07f617da094b83b7a9e5b2d37e8bf9172c61109
|
@ -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
|
@ -10,7 +10,6 @@ nacl: SRC_SUBDIRS -= src_network src_testlib
|
||||
contains(QT_CONFIG, dbus):SRC_SUBDIRS += src_dbus
|
||||
|
||||
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
|
||||
SRC_SUBDIRS += src_plugins
|
||||
@ -19,8 +18,6 @@ src_winmain.subdir = $$QT_SOURCE_TREE/src/winmain
|
||||
src_winmain.target = sub-winmain
|
||||
src_corelib.subdir = $$QT_SOURCE_TREE/src/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.target = sub-xml
|
||||
src_dbus.subdir = $$QT_SOURCE_TREE/src/dbus
|
||||
@ -65,7 +62,6 @@ src_platformsupport.target = sub-platformsupport
|
||||
src_declarative.depends += src_opengl
|
||||
src_webkit.depends += src_opengl
|
||||
}
|
||||
contains(QT_CONFIG, v8snapshot):src_v8.depends += src_tools_mkv8snapshot
|
||||
}
|
||||
|
||||
|
||||
|
@ -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
|
@ -2,7 +2,6 @@ TEMPLATE = subdirs
|
||||
|
||||
TOOLS_SUBDIRS = src_tools_bootstrap src_tools_moc src_tools_rcc
|
||||
!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
|
||||
src_tools_bootstrap.subdir = $$QT_SOURCE_TREE/src/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_uic.subdir = $$QT_SOURCE_TREE/src/tools/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 {
|
||||
# Set dependencies for each subdir
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
@ -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
|
||||
|
@ -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, ¬_user_equal);
|
||||
+
|
||||
+ __ CompareObjectType(r0, r2, r4, JS_OBJECT_TYPE);
|
||||
+ __ b(ne, ¬_user_equal);
|
||||
+
|
||||
+ __ CompareObjectType(r1, r3, r4, JS_OBJECT_TYPE);
|
||||
+ __ b(ne, ¬_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, ¬_user_equal);
|
||||
+
|
||||
+ __ bind(&user_equal);
|
||||
+
|
||||
+ __ Push(r0, r1);
|
||||
+ __ TailCallRuntime(Runtime::kUserObjectEquals, 2, 1);
|
||||
+
|
||||
+ __ bind(¬_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, ¬_user_equal);
|
||||
+ __ test(edx, Immediate(kSmiTagMask));
|
||||
+ __ j(zero, ¬_user_equal);
|
||||
+
|
||||
+ __ CmpObjectType(eax, JS_OBJECT_TYPE, ebx);
|
||||
+ __ j(not_equal, ¬_user_equal);
|
||||
+
|
||||
+ __ CmpObjectType(edx, JS_OBJECT_TYPE, ecx);
|
||||
+ __ j(not_equal, ¬_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(¬_user_equal);
|
||||
+
|
||||
+ __ bind(&user_equal);
|
||||
+
|
||||
+ __ pop(ebx); // Return address.
|
||||
+ __ push(eax);
|
||||
+ __ push(edx);
|
||||
+ __ push(ebx);
|
||||
+ __ TailCallRuntime(Runtime::kUserObjectEquals, 2, 1);
|
||||
+
|
||||
+ __ bind(¬_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, ¬_user_equal);
|
||||
+ __ JumpIfSmi(rdx, ¬_user_equal);
|
||||
+
|
||||
+ __ CmpObjectType(rax, JS_OBJECT_TYPE, rbx);
|
||||
+ __ j(not_equal, ¬_user_equal);
|
||||
+
|
||||
+ __ CmpObjectType(rdx, JS_OBJECT_TYPE, rcx);
|
||||
+ __ j(not_equal, ¬_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(¬_user_equal);
|
||||
+
|
||||
+ __ bind(&user_equal);
|
||||
+
|
||||
+ __ pop(rbx); // Return address.
|
||||
+ __ push(rax);
|
||||
+ __ push(rdx);
|
||||
+ __ push(rbx);
|
||||
+ __ TailCallRuntime(Runtime::kUserObjectEquals, 2, 1);
|
||||
+
|
||||
+ __ bind(¬_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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -1 +0,0 @@
|
||||
These patches apply cleanly against v8 at e123c9dfe54146f8bfca38841255f63a95a00a19
|
307
src/v8/v8.pri
307
src/v8/v8.pri
@ -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
|
@ -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
|
||||
}
|
@ -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
|
||||
}
|
||||
}
|
@ -4,7 +4,6 @@
|
||||
"QtPrintSupport" => "$basedir/src/printsupport",
|
||||
"QtOpenGL" => "$basedir/src/opengl",
|
||||
"QtCore" => "$basedir/src/corelib",
|
||||
"QtV8" => "$basedir/src/v8",
|
||||
"QtXml" => "$basedir/src/xml",
|
||||
"QtSql" => "$basedir/src/sql",
|
||||
"QtNetwork" => "$basedir/src/network",
|
||||
@ -13,10 +12,8 @@
|
||||
"QtPlatformSupport" => "$basedir/src/platformsupport",
|
||||
);
|
||||
%moduleheaders = ( # restrict the module headers to those found in relative path
|
||||
"QtV8" => "../3rdparty/v8/include",
|
||||
);
|
||||
@allmoduleheadersprivate = (
|
||||
"QtV8"
|
||||
);
|
||||
%classnames = (
|
||||
"qglobal.h" => "QtGlobal",
|
||||
@ -41,7 +38,6 @@
|
||||
"qtopenvgversion.h" => "QtOpenVGVersion",
|
||||
"qtsqlversion.h" => "QtSqlVersion",
|
||||
"qttestversion.h" => "QtTestVersion",
|
||||
"qtv8version.h" => "QtV8Version",
|
||||
"qtxmlversion.h" => "QtXmlVersion",
|
||||
);
|
||||
%mastercontent = (
|
||||
@ -63,7 +59,6 @@
|
||||
"QtOpenGL" => "$basedir/src/modules/qt_opengl.pri",
|
||||
"QtSql" => "$basedir/src/modules/qt_sql.pri",
|
||||
"QtTest" => "$basedir/src/modules/qt_testlib.pri",
|
||||
"QtV8" => "$basedir/src/modules/qt_v8.pri",
|
||||
"QtXml" => "$basedir/src/modules/qt_xml.pri",
|
||||
"QtPlatformSupport" => "$basedir/src/modules/qt_platformsupport.pri",
|
||||
);
|
||||
|
@ -9,7 +9,6 @@ SUBDIRS += \
|
||||
sql \
|
||||
testlib \
|
||||
tools \
|
||||
v8 \
|
||||
xml \
|
||||
other \
|
||||
widgets \
|
||||
@ -17,7 +16,6 @@ SUBDIRS += \
|
||||
cross_compile: SUBDIRS -= tools
|
||||
!contains(QT_CONFIG, opengl): SUBDIRS -= opengl
|
||||
!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
|
||||
mac {
|
||||
|
@ -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
|
@ -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
|
@ -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"
|
@ -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
|
@ -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;
|
||||
}
|
@ -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();
|
||||
}
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user