aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorAaron Kennedy <aaron.kennedy@nokia.com>2011-07-01 16:30:34 +1000
committerQt by Nokia <qt-info@nokia.com>2011-07-01 08:32:25 +0200
commitce8a1ef6f1a2868c6e4c19a56e94ca623b6b9889 (patch)
tree6ea2fd3c3174e99e2c55e331fb90d81880758ece /src
parentc4b0954b7de4f82e1d4ecc55bec59b3cef13c7f1 (diff)
Update V8
Change-Id: I2736cb8fffaace5cbb9e91d12a75bdedf3f80627 Reviewed-on: http://codereview.qt.nokia.com/988 Reviewed-by: Aaron Kennedy <aaron.kennedy@nokia.com>
Diffstat (limited to 'src')
m---------src/3rdparty/v80
-rw-r--r--src/v8/0001-Add-hashing-and-comparison-methods-to-v8-String.patch187
-rw-r--r--src/v8/0002-Add-a-bit-field-3-to-Map.patch14
-rw-r--r--src/v8/0003-Add-a-fallback-mode-for-named-property-interceptors.patch26
-rw-r--r--src/v8/0004-Generalize-external-object-resources.patch48
-rw-r--r--src/v8/0005-Introduce-a-QML-compilation-mode.patch484
-rw-r--r--src/v8/0006-Allow-access-to-the-calling-script-data.patch12
-rw-r--r--src/v8/0007-Fix-warnings.patch10
-rw-r--r--src/v8/0008-Add-custom-object-compare-callback.patch489
9 files changed, 1108 insertions, 162 deletions
diff --git a/src/3rdparty/v8 b/src/3rdparty/v8
-Subproject f7c8bc0d210ba97fad3261c5581f48221610f50
+Subproject eb2dadf516823ec342e6d75a3a78b2af7b1dea8
diff --git a/src/v8/0001-Add-hashing-and-comparison-methods-to-v8-String.patch b/src/v8/0001-Add-hashing-and-comparison-methods-to-v8-String.patch
index 57a0ae8bd3..e18e5bc69e 100644
--- a/src/v8/0001-Add-hashing-and-comparison-methods-to-v8-String.patch
+++ b/src/v8/0001-Add-hashing-and-comparison-methods-to-v8-String.patch
@@ -1,22 +1,25 @@
-From b828611412fae2c423b6e02d3fb266400492c4c0 Mon Sep 17 00:00:00 2001
+From 9a956953836844f1342ac012f4c2408405224fcd Mon Sep 17 00:00:00 2001
From: Aaron Kennedy <aaron.kennedy@nokia.com>
Date: Mon, 23 May 2011 15:47:20 +1000
-Subject: [PATCH 1/7] Add hashing and comparison methods to v8::String
+Subject: [PATCH 1/8] 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 | 20 ++++++++++++++++++
- src/api.cc | 28 ++++++++++++++++++++++++++
- src/objects.cc | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- src/objects.h | 3 ++
- 4 files changed, 111 insertions(+), 0 deletions(-)
+ include/v8.h | 43 +++++++++++++++++++++++++++++
+ src/api.cc | 39 +++++++++++++++++++++++++++
+ src/heap-inl.h | 2 +
+ src/heap.cc | 3 ++
+ src/objects-inl.h | 1 +
+ src/objects.cc | 77 ++++++++++++++++++++++++++++++++++++++++++++++++++++-
+ src/objects.h | 15 +++++++++-
+ 7 files changed, 177 insertions(+), 3 deletions(-)
diff --git a/include/v8.h b/include/v8.h
-index d15d024..bd48503 100644
+index d15d024..626f34c 100644
--- a/include/v8.h
+++ b/include/v8.h
-@@ -994,6 +994,24 @@ class String : public Primitive {
+@@ -994,6 +994,47 @@ class String : public Primitive {
V8EXPORT int Utf8Length() const;
/**
@@ -24,6 +27,29 @@ index d15d024..bd48503 100644
+ */
+ 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.
@@ -41,7 +67,7 @@ index d15d024..bd48503 100644
* 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
-@@ -1023,6 +1041,8 @@ class String : public Primitive {
+@@ -1023,6 +1064,8 @@ class String : public Primitive {
HINT_MANY_WRITES_EXPECTED = 1
};
@@ -51,10 +77,10 @@ index d15d024..bd48503 100644
int start = 0,
int length = -1,
diff --git a/src/api.cc b/src/api.cc
-index a2373cd..f509673 100644
+index a2373cd..0d860bd 100644
--- a/src/api.cc
+++ b/src/api.cc
-@@ -3284,6 +3284,34 @@ int String::Utf8Length() const {
+@@ -3284,6 +3284,45 @@ int String::Utf8Length() const {
return str->Utf8Length();
}
@@ -64,6 +90,17 @@ index a2373cd..f509673 100644
+ 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;
+}
@@ -89,8 +126,68 @@ index a2373cd..f509673 100644
int String::WriteUtf8(char* buffer,
int capacity,
+diff --git a/src/heap-inl.h b/src/heap-inl.h
+index 99737ed..f4fce7b 100644
+--- a/src/heap-inl.h
++++ b/src/heap-inl.h
+@@ -93,6 +93,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());
+
+@@ -126,6 +127,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 2b6c11f..930c97b 100644
+--- a/src/heap.cc
++++ b/src/heap.cc
+@@ -3519,6 +3519,7 @@ MaybeObject* Heap::AllocateInternalSymbol(unibrow::CharacterStream* buffer,
+ String* answer = String::cast(result);
+ answer->set_length(chars);
+ answer->set_hash_field(hash_field);
++ SeqString::cast(result)->set_symbol_id(0);
+
+ ASSERT_EQ(size, answer->Size());
+
+@@ -3561,6 +3562,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;
+ }
+@@ -3596,6 +3598,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 65aec5d..c82080d 100644
+--- a/src/objects-inl.h
++++ b/src/objects-inl.h
+@@ -1924,6 +1924,7 @@ INT_ACCESSORS(ExternalArray, length, kLengthOffset)
+
+
+ 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 df61956..5bd7f95 100644
+index df61956..877da3d 100644
--- a/src/objects.cc
+++ b/src/objects.cc
@@ -5346,6 +5346,66 @@ static inline bool CompareStringContentsPartial(Isolate* isolate,
@@ -160,8 +257,34 @@ index df61956..5bd7f95 100644
bool String::SlowEquals(String* other) {
// Fast check: negative check with lengths.
+@@ -8655,9 +8715,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(next_symbol_id++);
++ break;
++ }
++ }
++ }
++ return result;
+ }
++
++ static Atomic32 next_symbol_id;
+ };
++Atomic32 AsciiSymbolKey::next_symbol_id = 1;
+
+
+ class TwoByteSymbolKey : public SequentialSymbolKey<uc16> {
diff --git a/src/objects.h b/src/objects.h
-index e966b3d..f4c27d2 100644
+index e966b3d..6e26f57 100644
--- a/src/objects.h
+++ b/src/objects.h
@@ -5359,6 +5359,9 @@ class String: public HeapObject {
@@ -174,6 +297,42 @@ index e966b3d..f4c27d2 100644
// 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
+@@ -5610,9 +5613,17 @@ class String: public HeapObject {
+ class SeqString: public String {
+ public:
+
++ // Get and set the symbol id of the string
++ inline int symbol_id();
++ inline void set_symbol_id(int value);
++
+ // Casting.
+ static inline SeqString* cast(Object* obj);
+
++ // Layout description.
++ static const int kSymbolIdOffset = String::kSize;
++ static const int kSize = kSymbolIdOffset + kPointerSize;
++
+ private:
+ DISALLOW_IMPLICIT_CONSTRUCTORS(SeqString);
+ };
+@@ -5647,7 +5658,7 @@ class SeqAsciiString: public SeqString {
+ }
+
+ // Layout description.
+- static const int kHeaderSize = String::kSize;
++ static const int kHeaderSize = SeqString::kSize;
+ static const int kAlignedSize = POINTER_SIZE_ALIGN(kHeaderSize);
+
+ // Maximal memory usage for a single sequential ASCII string.
+@@ -5701,7 +5712,7 @@ class SeqTwoByteString: public SeqString {
+ }
+
+ // Layout description.
+- static const int kHeaderSize = String::kSize;
++ static const int kHeaderSize = SeqString::kSize;
+ static const int kAlignedSize = POINTER_SIZE_ALIGN(kHeaderSize);
+
+ // Maximal memory usage for a single sequential two-byte string.
--
1.7.2.3
diff --git a/src/v8/0002-Add-a-bit-field-3-to-Map.patch b/src/v8/0002-Add-a-bit-field-3-to-Map.patch
index 86820d7127..98cc017883 100644
--- a/src/v8/0002-Add-a-bit-field-3-to-Map.patch
+++ b/src/v8/0002-Add-a-bit-field-3-to-Map.patch
@@ -1,7 +1,7 @@
-From f2d11bae75512a1173da7b9f9edfaeeb1a1e73ce Mon Sep 17 00:00:00 2001
+From 4ce6693b28f0a699acd91c0ae88ae917cc273e9a Mon Sep 17 00:00:00 2001
From: Aaron Kennedy <aaron.kennedy@nokia.com>
Date: Mon, 23 May 2011 15:55:26 +1000
-Subject: [PATCH 2/7] Add a bit field 3 to Map
+Subject: [PATCH 2/8] Add a bit field 3 to Map
Bit field 3 will be used to add QML specific map flags.
---
@@ -12,7 +12,7 @@ Bit field 3 will be used to add QML specific map flags.
4 files changed, 22 insertions(+), 1 deletions(-)
diff --git a/src/heap.cc b/src/heap.cc
-index 2b6c11f..4a58bf6 100644
+index 930c97b..900f462 100644
--- a/src/heap.cc
+++ b/src/heap.cc
@@ -1573,6 +1573,7 @@ MaybeObject* Heap::AllocatePartialMap(InstanceType instance_type,
@@ -32,10 +32,10 @@ index 2b6c11f..4a58bf6 100644
// If the map object is aligned fill the padding area with Smi 0 objects.
if (Map::kPadStart < Map::kSize) {
diff --git a/src/objects-inl.h b/src/objects-inl.h
-index 65aec5d..bbe05f6 100644
+index c82080d..cce3edd 100644
--- a/src/objects-inl.h
+++ b/src/objects-inl.h
-@@ -2429,6 +2429,16 @@ void Map::set_bit_field2(byte value) {
+@@ -2430,6 +2430,16 @@ void Map::set_bit_field2(byte value) {
}
@@ -53,7 +53,7 @@ index 65aec5d..bbe05f6 100644
if (value) {
set_bit_field(bit_field() | (1 << kHasNonInstancePrototype));
diff --git a/src/objects.cc b/src/objects.cc
-index 5bd7f95..92ab958 100644
+index 877da3d..2409ea3 100644
--- a/src/objects.cc
+++ b/src/objects.cc
@@ -3614,6 +3614,7 @@ MaybeObject* Map::CopyDropDescriptors() {
@@ -73,7 +73,7 @@ index 5bd7f95..92ab958 100644
Map::cast(result)->set_is_shared(sharing == SHARED_NORMALIZED_MAP);
diff --git a/src/objects.h b/src/objects.h
-index f4c27d2..a61733e 100644
+index 6e26f57..07e1089 100644
--- a/src/objects.h
+++ b/src/objects.h
@@ -3597,6 +3597,10 @@ class Map: public HeapObject {
diff --git a/src/v8/0003-Add-a-fallback-mode-for-named-property-interceptors.patch b/src/v8/0003-Add-a-fallback-mode-for-named-property-interceptors.patch
index cef7012cfb..6af02cfa0c 100644
--- a/src/v8/0003-Add-a-fallback-mode-for-named-property-interceptors.patch
+++ b/src/v8/0003-Add-a-fallback-mode-for-named-property-interceptors.patch
@@ -1,7 +1,7 @@
-From 7ccd4af88f3323405ef834acabee15e1e6748474 Mon Sep 17 00:00:00 2001
+From 5adbbff4a7f09a02d5c2d9b4e15dde89080e2405 Mon Sep 17 00:00:00 2001
From: Aaron Kennedy <aaron.kennedy@nokia.com>
Date: Mon, 23 May 2011 16:21:02 +1000
-Subject: [PATCH 3/7] Add a "fallback" mode for named property interceptors
+Subject: [PATCH 3/8] 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
@@ -24,10 +24,10 @@ declarations.
9 files changed, 99 insertions(+), 18 deletions(-)
diff --git a/include/v8.h b/include/v8.h
-index bd48503..94da79c 100644
+index 626f34c..06085ec 100644
--- a/include/v8.h
+++ b/include/v8.h
-@@ -2145,6 +2145,7 @@ class V8EXPORT FunctionTemplate : public Template {
+@@ -2168,6 +2168,7 @@ class V8EXPORT FunctionTemplate : public Template {
NamedPropertyQuery query,
NamedPropertyDeleter remover,
NamedPropertyEnumerator enumerator,
@@ -35,7 +35,7 @@ index bd48503..94da79c 100644
Handle<Value> data);
void SetIndexedInstancePropertyHandler(IndexedPropertyGetter getter,
IndexedPropertySetter setter,
-@@ -2229,6 +2230,13 @@ class V8EXPORT ObjectTemplate : public Template {
+@@ -2252,6 +2253,13 @@ class V8EXPORT ObjectTemplate : public Template {
NamedPropertyEnumerator enumerator = 0,
Handle<Value> data = Handle<Value>());
@@ -50,7 +50,7 @@ index bd48503..94da79c 100644
* Sets an indexed property handler on the object template.
*
diff --git a/src/api.cc b/src/api.cc
-index f509673..2ac4395 100644
+index 0d860bd..c20b062 100644
--- a/src/api.cc
+++ b/src/api.cc
@@ -981,6 +981,7 @@ void FunctionTemplate::SetNamedInstancePropertyHandler(
@@ -151,10 +151,10 @@ index 3839f37..4b42506 100644
Handle<Object> SetProperty(Handle<Object> object,
Handle<Object> key,
diff --git a/src/objects-inl.h b/src/objects-inl.h
-index bbe05f6..0c09e84 100644
+index cce3edd..6aaca2f 100644
--- a/src/objects-inl.h
+++ b/src/objects-inl.h
-@@ -2520,6 +2520,21 @@ bool Map::is_shared() {
+@@ -2521,6 +2521,21 @@ bool Map::is_shared() {
}
@@ -176,7 +176,7 @@ index bbe05f6..0c09e84 100644
JSFunction* Map::unchecked_constructor() {
return reinterpret_cast<JSFunction*>(READ_FIELD(this, kConstructorOffset));
}
-@@ -2969,6 +2984,7 @@ ACCESSORS(InterceptorInfo, query, Object, kQueryOffset)
+@@ -2970,6 +2985,7 @@ ACCESSORS(InterceptorInfo, query, Object, kQueryOffset)
ACCESSORS(InterceptorInfo, deleter, Object, kDeleterOffset)
ACCESSORS(InterceptorInfo, enumerator, Object, kEnumeratorOffset)
ACCESSORS(InterceptorInfo, data, Object, kDataOffset)
@@ -185,7 +185,7 @@ index bbe05f6..0c09e84 100644
ACCESSORS(CallHandlerInfo, callback, Object, kCallbackOffset)
ACCESSORS(CallHandlerInfo, data, Object, kDataOffset)
diff --git a/src/objects.cc b/src/objects.cc
-index 92ab958..08d130e 100644
+index 2409ea3..f1e4c8c 100644
--- a/src/objects.cc
+++ b/src/objects.cc
@@ -1712,9 +1712,10 @@ MaybeObject* JSObject::SetPropertyWithInterceptor(
@@ -246,7 +246,7 @@ index 92ab958..08d130e 100644
}
result->NotFound();
diff --git a/src/objects.h b/src/objects.h
-index a61733e..3fdc69f 100644
+index 07e1089..a209cd0 100644
--- a/src/objects.h
+++ b/src/objects.h
@@ -1405,7 +1405,8 @@ class JSObject: public HeapObject {
@@ -291,7 +291,7 @@ index a61733e..3fdc69f 100644
// Layout of the default cache. It holds alternating name and code objects.
static const int kCodeCacheEntrySize = 2;
-@@ -6268,6 +6276,7 @@ class InterceptorInfo: public Struct {
+@@ -6276,6 +6284,7 @@ class InterceptorInfo: public Struct {
DECL_ACCESSORS(deleter, Object)
DECL_ACCESSORS(enumerator, Object)
DECL_ACCESSORS(data, Object)
@@ -299,7 +299,7 @@ index a61733e..3fdc69f 100644
static inline InterceptorInfo* cast(Object* obj);
-@@ -6287,7 +6296,8 @@ class InterceptorInfo: public Struct {
+@@ -6295,7 +6304,8 @@ class InterceptorInfo: public Struct {
static const int kDeleterOffset = kQueryOffset + kPointerSize;
static const int kEnumeratorOffset = kDeleterOffset + kPointerSize;
static const int kDataOffset = kEnumeratorOffset + kPointerSize;
diff --git a/src/v8/0004-Generalize-external-object-resources.patch b/src/v8/0004-Generalize-external-object-resources.patch
index 9c30763994..3d5686fe27 100644
--- a/src/v8/0004-Generalize-external-object-resources.patch
+++ b/src/v8/0004-Generalize-external-object-resources.patch
@@ -1,7 +1,7 @@
-From a9108d655fcd8ffa45a32257160cc10eaf0256ee Mon Sep 17 00:00:00 2001
+From 8f640251aeac30f08ddb7bc4c0fe6ba6ff7eabdd Mon Sep 17 00:00:00 2001
From: Aaron Kennedy <aaron.kennedy@nokia.com>
Date: Mon, 23 May 2011 16:55:35 +1000
-Subject: [PATCH 4/7] Generalize external object resources
+Subject: [PATCH 4/8] Generalize external object resources
V8 was already able to manage and finalize an external string
resource. This change generalizes that mechanism to handle a
@@ -31,10 +31,10 @@ object space.
11 files changed, 280 insertions(+), 115 deletions(-)
diff --git a/include/v8.h b/include/v8.h
-index 94da79c..b377c53 100644
+index 06085ec..9740251 100644
--- a/include/v8.h
+++ b/include/v8.h
-@@ -1606,6 +1606,25 @@ class Object : public Value {
+@@ -1629,6 +1629,25 @@ class Object : public Value {
/** Sets a native pointer in an internal field. */
V8EXPORT void SetPointerInInternalField(int index, void* value);
@@ -60,7 +60,7 @@ index 94da79c..b377c53 100644
// Testers for local properties.
V8EXPORT bool HasRealNamedProperty(Handle<String> key);
V8EXPORT bool HasRealIndexedProperty(uint32_t index);
-@@ -2307,6 +2326,12 @@ class V8EXPORT ObjectTemplate : public Template {
+@@ -2330,6 +2349,12 @@ class V8EXPORT ObjectTemplate : public Template {
*/
void SetInternalFieldCount(int value);
@@ -74,7 +74,7 @@ index 94da79c..b377c53 100644
ObjectTemplate();
static Local<ObjectTemplate> New(Handle<FunctionTemplate> constructor);
diff --git a/src/api.cc b/src/api.cc
-index 2ac4395..3137d6c 100644
+index c20b062..d81ece8 100644
--- a/src/api.cc
+++ b/src/api.cc
@@ -1294,6 +1294,34 @@ void ObjectTemplate::SetInternalFieldCount(int value) {
@@ -112,7 +112,7 @@ index 2ac4395..3137d6c 100644
// --- S c r i p t D a t a ---
-@@ -3637,6 +3665,34 @@ void v8::Object::SetPointerInInternalField(int index, void* value) {
+@@ -3648,6 +3676,34 @@ void v8::Object::SetPointerInInternalField(int index, void* value) {
}
@@ -147,7 +147,7 @@ index 2ac4395..3137d6c 100644
// --- E n v i r o n m e n t ---
-@@ -4129,7 +4185,7 @@ Local<String> v8::String::NewExternal(
+@@ -4140,7 +4196,7 @@ Local<String> v8::String::NewExternal(
LOG_API(isolate, "String::NewExternal");
ENTER_V8(isolate);
i::Handle<i::String> result = NewExternalStringHandle(isolate, resource);
@@ -156,7 +156,7 @@ index 2ac4395..3137d6c 100644
return Utils::ToLocal(result);
}
-@@ -4147,7 +4203,7 @@ bool v8::String::MakeExternal(v8::String::ExternalStringResource* resource) {
+@@ -4158,7 +4214,7 @@ bool v8::String::MakeExternal(v8::String::ExternalStringResource* resource) {
}
bool result = obj->MakeExternal(resource);
if (result && !obj->IsSymbol()) {
@@ -165,7 +165,7 @@ index 2ac4395..3137d6c 100644
}
return result;
}
-@@ -4160,7 +4216,7 @@ Local<String> v8::String::NewExternal(
+@@ -4171,7 +4227,7 @@ Local<String> v8::String::NewExternal(
LOG_API(isolate, "String::NewExternal");
ENTER_V8(isolate);
i::Handle<i::String> result = NewExternalAsciiStringHandle(isolate, resource);
@@ -174,7 +174,7 @@ index 2ac4395..3137d6c 100644
return Utils::ToLocal(result);
}
-@@ -4179,7 +4235,7 @@ bool v8::String::MakeExternal(
+@@ -4190,7 +4246,7 @@ bool v8::String::MakeExternal(
}
bool result = obj->MakeExternal(resource);
if (result && !obj->IsSymbol()) {
@@ -244,10 +244,10 @@ index dcdc645..d530a75 100644
if (obj->undetectable()) {
map->set_is_undetectable();
diff --git a/src/heap-inl.h b/src/heap-inl.h
-index 99737ed..84f8b39 100644
+index f4fce7b..58e7adf 100644
--- a/src/heap-inl.h
+++ b/src/heap-inl.h
-@@ -203,21 +203,36 @@ MaybeObject* Heap::NumberFromUint32(uint32_t value) {
+@@ -205,21 +205,36 @@ MaybeObject* Heap::NumberFromUint32(uint32_t value) {
}
@@ -298,7 +298,7 @@ index 99737ed..84f8b39 100644
}
-@@ -554,53 +569,63 @@ inline bool Heap::allow_allocation(bool new_state) {
+@@ -556,53 +571,63 @@ inline bool Heap::allow_allocation(bool new_state) {
#endif
@@ -387,7 +387,7 @@ index 99737ed..84f8b39 100644
}
diff --git a/src/heap.cc b/src/heap.cc
-index 4a58bf6..46df787 100644
+index 900f462..bf2940e 100644
--- a/src/heap.cc
+++ b/src/heap.cc
@@ -155,7 +155,7 @@ Heap::Heap()
@@ -476,7 +476,7 @@ index 4a58bf6..46df787 100644
}
-@@ -4465,7 +4465,7 @@ void Heap::IterateWeakRoots(ObjectVisitor* v, VisitMode mode) {
+@@ -4468,7 +4468,7 @@ void Heap::IterateWeakRoots(ObjectVisitor* v, VisitMode mode) {
v->Synchronize("symbol_table");
if (mode != VISIT_ALL_IN_SCAVENGE) {
// Scavenge collections have special processing for this.
@@ -485,7 +485,7 @@ index 4a58bf6..46df787 100644
}
v->Synchronize("external_string_table");
}
-@@ -4967,7 +4967,7 @@ void Heap::TearDown() {
+@@ -4970,7 +4970,7 @@ void Heap::TearDown() {
isolate_->global_handles()->TearDown();
@@ -494,7 +494,7 @@ index 4a58bf6..46df787 100644
new_space_.TearDown();
-@@ -5832,31 +5832,31 @@ void TranscendentalCache::Clear() {
+@@ -5835,31 +5835,31 @@ void TranscendentalCache::Clear() {
}
@@ -747,7 +747,7 @@ index 68a5062..1b1e361 100644
// All pointers were updated. Update auxiliary allocation info.
heap->IncrementYoungSurvivorsCounter(survivors_size);
diff --git a/src/objects-inl.h b/src/objects-inl.h
-index 0c09e84..a205f02 100644
+index 6aaca2f..231b835 100644
--- a/src/objects-inl.h
+++ b/src/objects-inl.h
@@ -1392,13 +1392,13 @@ int JSObject::GetInternalFieldCount() {
@@ -806,7 +806,7 @@ index 0c09e84..a205f02 100644
// 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.
-@@ -2520,6 +2537,20 @@ bool Map::is_shared() {
+@@ -2521,6 +2538,20 @@ bool Map::is_shared() {
}
@@ -827,7 +827,7 @@ index 0c09e84..a205f02 100644
void Map::set_named_interceptor_is_fallback(bool value)
{
if (value) {
-@@ -3016,6 +3047,8 @@ ACCESSORS(FunctionTemplateInfo, flag, Smi, kFlagOffset)
+@@ -3017,6 +3048,8 @@ ACCESSORS(FunctionTemplateInfo, flag, Smi, kFlagOffset)
ACCESSORS(ObjectTemplateInfo, constructor, Object, kConstructorOffset)
ACCESSORS(ObjectTemplateInfo, internal_field_count, Object,
kInternalFieldCountOffset)
@@ -837,7 +837,7 @@ index 0c09e84..a205f02 100644
ACCESSORS(SignatureInfo, receiver, Object, kReceiverOffset)
ACCESSORS(SignatureInfo, args, Object, kArgsOffset)
diff --git a/src/objects.h b/src/objects.h
-index 3fdc69f..439ad1e 100644
+index a209cd0..1bdb5c7 100644
--- a/src/objects.h
+++ b/src/objects.h
@@ -1636,6 +1636,9 @@ class JSObject: public HeapObject {
@@ -871,7 +871,7 @@ index 3fdc69f..439ad1e 100644
// Layout of the default cache. It holds alternating name and code objects.
static const int kCodeCacheEntrySize = 2;
-@@ -6418,6 +6428,7 @@ class ObjectTemplateInfo: public TemplateInfo {
+@@ -6426,6 +6436,7 @@ class ObjectTemplateInfo: public TemplateInfo {
public:
DECL_ACCESSORS(constructor, Object)
DECL_ACCESSORS(internal_field_count, Object)
@@ -879,7 +879,7 @@ index 3fdc69f..439ad1e 100644
static inline ObjectTemplateInfo* cast(Object* obj);
-@@ -6434,7 +6445,8 @@ class ObjectTemplateInfo: public TemplateInfo {
+@@ -6442,7 +6453,8 @@ class ObjectTemplateInfo: public TemplateInfo {
static const int kConstructorOffset = TemplateInfo::kHeaderSize;
static const int kInternalFieldCountOffset =
kConstructorOffset + kPointerSize;
diff --git a/src/v8/0005-Introduce-a-QML-compilation-mode.patch b/src/v8/0005-Introduce-a-QML-compilation-mode.patch
index 5b85166f6b..930e2b9453 100644
--- a/src/v8/0005-Introduce-a-QML-compilation-mode.patch
+++ b/src/v8/0005-Introduce-a-QML-compilation-mode.patch
@@ -1,7 +1,7 @@
-From 2762e881e1990169c3d9d9f02d5db56d79de79ba Mon Sep 17 00:00:00 2001
+From de8b6a719219677dc8e34248de7836369bf1034d Mon Sep 17 00:00:00 2001
From: Aaron Kennedy <aaron.kennedy@nokia.com>
Date: Mon, 23 May 2011 18:26:19 +1000
-Subject: [PATCH 5/7] Introduce a QML compilation mode
+Subject: [PATCH 5/8] Introduce a QML compilation mode
In QML mode, there is a second global object - known as the QML
global object. During property resolution, if a property is not
@@ -15,43 +15,55 @@ closures etc. created during the run will retain a reference to this
object, so different objects can be passed in different script
runs.
---
- include/v8.h | 18 ++++++++--
- src/api.cc | 52 ++++++++++++++++++++++++-----
- src/arm/code-stubs-arm.cc | 4 ++
- src/arm/full-codegen-arm.cc | 21 +++++++-----
- src/arm/macro-assembler-arm.h | 5 +++
- src/ast-inl.h | 5 +++
- src/ast.h | 1 +
- src/compiler.cc | 15 +++++++-
- src/compiler.h | 24 +++++++++++---
- src/contexts.cc | 23 +++++++++++++
- src/contexts.h | 4 ++
- src/execution.cc | 28 ++++++++++++++--
- src/execution.h | 6 +++
- src/full-codegen.cc | 3 +-
- src/full-codegen.h | 1 +
- src/heap.cc | 2 +
- src/ia32/code-stubs-ia32.cc | 7 ++++
- src/ia32/full-codegen-ia32.cc | 21 +++++++-----
- src/ia32/macro-assembler-ia32.h | 5 +++
- src/objects-inl.h | 12 +++++++
- src/objects.h | 5 +++
- src/parser.cc | 27 +++++++++++++--
- src/parser.h | 4 ++-
- src/prettyprinter.cc | 3 ++
- src/runtime.cc | 68 +++++++++++++++++++++++++--------------
- src/runtime.h | 8 ++--
- src/scopes.cc | 16 +++++++++
- src/scopes.h | 7 ++++
- src/variables.cc | 3 +-
- src/variables.h | 5 +++
- src/x64/code-stubs-x64.cc | 4 ++
- src/x64/full-codegen-x64.cc | 21 +++++++-----
- src/x64/macro-assembler-x64.h | 5 +++
- 33 files changed, 347 insertions(+), 86 deletions(-)
+ include/v8.h | 18 ++++++++--
+ src/api.cc | 52 ++++++++++++++++++++++++-----
+ src/arm/code-stubs-arm.cc | 4 ++
+ src/arm/full-codegen-arm.cc | 26 ++++++++------
+ src/arm/lithium-arm.cc | 2 +-
+ src/arm/lithium-arm.h | 6 +++-
+ src/arm/lithium-codegen-arm.cc | 7 ++--
+ src/arm/macro-assembler-arm.h | 5 +++
+ src/ast-inl.h | 5 +++
+ src/ast.h | 1 +
+ src/code-stubs.h | 2 +-
+ src/compiler.cc | 15 +++++++-
+ src/compiler.h | 22 ++++++++++--
+ src/contexts.cc | 23 +++++++++++++
+ src/contexts.h | 4 ++
+ src/execution.cc | 28 +++++++++++++--
+ src/execution.h | 6 +++
+ src/full-codegen.cc | 3 +-
+ src/full-codegen.h | 1 +
+ src/heap.cc | 2 +
+ src/hydrogen-instructions.h | 10 ++++-
+ src/hydrogen.cc | 2 +
+ src/ia32/code-stubs-ia32.cc | 7 ++++
+ src/ia32/full-codegen-ia32.cc | 26 ++++++++------
+ src/ia32/lithium-codegen-ia32.cc | 7 ++--
+ src/ia32/lithium-ia32.cc | 2 +-
+ src/ia32/lithium-ia32.h | 6 +++-
+ src/ia32/macro-assembler-ia32.h | 5 +++
+ src/objects-inl.h | 12 +++++++
+ src/objects.h | 5 +++
+ src/parser.cc | 27 +++++++++++++--
+ src/parser.h | 4 ++-
+ src/prettyprinter.cc | 3 ++
+ src/runtime.cc | 68 ++++++++++++++++++++++++-------------
+ src/runtime.h | 8 ++--
+ src/scopes.cc | 10 +++++
+ src/scopes.h | 7 ++++
+ src/variables.cc | 3 +-
+ src/variables.h | 5 +++
+ src/x64/code-stubs-x64.cc | 4 ++
+ src/x64/full-codegen-x64.cc | 26 ++++++++------
+ src/x64/lithium-codegen-x64.cc | 7 ++--
+ src/x64/lithium-x64.cc | 2 +-
+ src/x64/lithium-x64.h | 6 +++
+ src/x64/macro-assembler-x64.h | 5 +++
+ 45 files changed, 391 insertions(+), 108 deletions(-)
diff --git a/include/v8.h b/include/v8.h
-index b377c53..a67feb2 100644
+index 9740251..d04b73e 100644
--- a/include/v8.h
+++ b/include/v8.h
@@ -577,6 +577,10 @@ class ScriptOrigin {
@@ -113,7 +125,7 @@ index b377c53..a67feb2 100644
/**
* Returns the script id value.
-@@ -3302,6 +3311,7 @@ class V8EXPORT Context {
+@@ -3325,6 +3334,7 @@ class V8EXPORT Context {
* JavaScript frames an empty handle is returned.
*/
static Local<Context> GetCalling();
@@ -122,7 +134,7 @@ index b377c53..a67feb2 100644
/**
* Sets the security token for the context. To access an object in
diff --git a/src/api.cc b/src/api.cc
-index 3137d6c..61ed79e 100644
+index d81ece8..0635f34 100644
--- a/src/api.cc
+++ b/src/api.cc
@@ -1372,7 +1372,8 @@ ScriptData* ScriptData::New(const char* data, int length) {
@@ -207,7 +219,7 @@ index 3137d6c..61ed79e 100644
EXCEPTION_BAILOUT_CHECK(isolate, Local<Value>());
raw_result = *result;
}
-@@ -3928,6 +3938,30 @@ v8::Local<v8::Context> Context::GetCalling() {
+@@ -3939,6 +3949,30 @@ v8::Local<v8::Context> Context::GetCalling() {
}
@@ -254,10 +266,26 @@ index 8c147f9..a2626bf 100644
__ LoadRoot(r1, Heap::kUndefinedValueRootIndex);
for (int i = Context::MIN_CONTEXT_SLOTS; i < length; i++) {
diff --git a/src/arm/full-codegen-arm.cc b/src/arm/full-codegen-arm.cc
-index 871b453..f132de6 100644
+index 871b453..a69f10d 100644
--- a/src/arm/full-codegen-arm.cc
+++ b/src/arm/full-codegen-arm.cc
-@@ -1247,9 +1247,9 @@ void FullCodeGenerator::EmitLoadGlobalSlotCheckExtensions(
+@@ -154,12 +154,13 @@ void FullCodeGenerator::Generate(CompilationInfo* info) {
+
+ // Possibly allocate a local context.
+ int heap_slots = scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS;
+- if (heap_slots > 0) {
++ if (heap_slots > 0 ||
++ (scope()->is_qml_mode() && scope()->is_global_scope())) {
+ Comment cmnt(masm_, "[ Allocate local context");
+ // Argument to NewContext is the function, which is in r1.
+ __ push(r1);
+ if (heap_slots <= FastNewContextStub::kMaximumSlots) {
+- FastNewContextStub stub(heap_slots);
++ FastNewContextStub stub((heap_slots < 0)?0:heap_slots);
+ __ CallStub(&stub);
+ } else {
+ __ CallRuntime(Runtime::kNewContext, 1);
+@@ -1247,9 +1248,9 @@ void FullCodeGenerator::EmitLoadGlobalSlotCheckExtensions(
__ bind(&fast);
}
@@ -269,7 +297,7 @@ index 871b453..f132de6 100644
? RelocInfo::CODE_TARGET
: RelocInfo::CODE_TARGET_CONTEXT;
Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize();
-@@ -1268,10 +1268,10 @@ void FullCodeGenerator::EmitVariableLoad(Variable* var) {
+@@ -1268,10 +1269,10 @@ void FullCodeGenerator::EmitVariableLoad(Variable* var) {
Comment cmnt(masm_, "Global variable");
// Use inline caching. Variable name is passed in r2 and the global
// object (receiver) in r0.
@@ -282,7 +310,7 @@ index 871b453..f132de6 100644
context()->Plug(r0);
} else if (slot != NULL && slot->type() == Slot::LOOKUP) {
-@@ -1893,11 +1893,11 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var,
+@@ -1893,11 +1894,11 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var,
// assignment. Right-hand-side value is passed in r0, variable name in
// r2, and the global object in r1.
__ mov(r2, Operand(var->name()));
@@ -296,7 +324,7 @@ index 871b453..f132de6 100644
} else if (op == Token::INIT_CONST) {
// Like var declarations, const declarations are hoisted to function
-@@ -2184,10 +2184,13 @@ void FullCodeGenerator::EmitResolvePossiblyDirectEval(ResolveEvalFlag flag,
+@@ -2184,10 +2185,13 @@ void FullCodeGenerator::EmitResolvePossiblyDirectEval(ResolveEvalFlag flag,
// Push the strict mode flag.
__ mov(r1, Operand(Smi::FromInt(strict_mode_flag())));
__ push(r1);
@@ -311,7 +339,7 @@ index 871b453..f132de6 100644
}
-@@ -2263,9 +2266,9 @@ void FullCodeGenerator::VisitCall(Call* expr) {
+@@ -2263,9 +2267,9 @@ void FullCodeGenerator::VisitCall(Call* expr) {
context()->DropAndPlug(1, r0);
} else if (var != NULL && !var->is_this() && var->is_global()) {
// Push global object as receiver for the call IC.
@@ -323,6 +351,71 @@ index 871b453..f132de6 100644
} else if (var != NULL && var->AsSlot() != NULL &&
var->AsSlot()->type() == Slot::LOOKUP) {
// Call to a lookup slot (dynamically introduced variable).
+diff --git a/src/arm/lithium-arm.cc b/src/arm/lithium-arm.cc
+index 3f1d15b..8406a96 100644
+--- a/src/arm/lithium-arm.cc
++++ b/src/arm/lithium-arm.cc
+@@ -1195,7 +1195,7 @@ LInstruction* LChunkBuilder::DoOuterContext(HOuterContext* instr) {
+
+ LInstruction* LChunkBuilder::DoGlobalObject(HGlobalObject* instr) {
+ LOperand* context = UseRegisterAtStart(instr->value());
+- return DefineAsRegister(new LGlobalObject(context));
++ return DefineAsRegister(new LGlobalObject(context, instr->qml_global()));
+ }
+
+
+diff --git a/src/arm/lithium-arm.h b/src/arm/lithium-arm.h
+index 6da7c86..10b901f 100644
+--- a/src/arm/lithium-arm.h
++++ b/src/arm/lithium-arm.h
+@@ -1378,13 +1378,17 @@ class LOuterContext: public LTemplateInstruction<1, 1, 0> {
+
+ class LGlobalObject: public LTemplateInstruction<1, 1, 0> {
+ public:
+- explicit LGlobalObject(LOperand* context) {
++ explicit LGlobalObject(LOperand* context, bool qml_global) {
+ inputs_[0] = context;
++ qml_global_ = qml_global;
+ }
+
+ DECLARE_CONCRETE_INSTRUCTION(GlobalObject, "global-object")
+
+ LOperand* context() { return InputAt(0); }
++ bool qml_global() { return qml_global_; }
++ private:
++ bool qml_global_;
+ };
+
+
+diff --git a/src/arm/lithium-codegen-arm.cc b/src/arm/lithium-codegen-arm.cc
+index 4912449..db114ea 100644
+--- a/src/arm/lithium-codegen-arm.cc
++++ b/src/arm/lithium-codegen-arm.cc
+@@ -166,12 +166,13 @@ bool LCodeGen::GeneratePrologue() {
+
+ // Possibly allocate a local context.
+ int heap_slots = scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS;
+- if (heap_slots > 0) {
++ if (heap_slots > 0 ||
++ (scope()->is_qml_mode() && scope()->is_global_scope())) {
+ Comment(";;; Allocate local context");
+ // Argument to NewContext is the function, which is in r1.
+ __ push(r1);
+ if (heap_slots <= FastNewContextStub::kMaximumSlots) {
+- FastNewContextStub stub(heap_slots);
++ FastNewContextStub stub((heap_slots < 0)?0:heap_slots);
+ __ CallStub(&stub);
+ } else {
+ __ CallRuntime(Runtime::kNewContext, 1);
+@@ -2664,7 +2665,7 @@ void LCodeGen::DoOuterContext(LOuterContext* instr) {
+ void LCodeGen::DoGlobalObject(LGlobalObject* instr) {
+ Register context = ToRegister(instr->context());
+ Register result = ToRegister(instr->result());
+- __ ldr(result, ContextOperand(cp, Context::GLOBAL_INDEX));
++ __ ldr(result, ContextOperand(cp, instr->qml_global()?Context::QML_GLOBAL_INDEX:Context::GLOBAL_INDEX));
+ }
+
+
diff --git a/src/arm/macro-assembler-arm.h b/src/arm/macro-assembler-arm.h
index ab5efb0..d40cdbc 100644
--- a/src/arm/macro-assembler-arm.h
@@ -367,6 +460,19 @@ index 65a25a9..f790dc0 100644
int materialized_literal_count() { return materialized_literal_count_; }
int expected_property_count() { return expected_property_count_; }
+diff --git a/src/code-stubs.h b/src/code-stubs.h
+index 56ef072..37e5383 100644
+--- a/src/code-stubs.h
++++ b/src/code-stubs.h
+@@ -303,7 +303,7 @@ class FastNewContextStub : public CodeStub {
+ static const int kMaximumSlots = 64;
+
+ explicit FastNewContextStub(int slots) : slots_(slots) {
+- ASSERT(slots_ > 0 && slots <= kMaximumSlots);
++ ASSERT(slots_ >= 0 && slots <= kMaximumSlots);
+ }
+
+ void Generate(MacroAssembler* masm);
diff --git a/src/compiler.cc b/src/compiler.cc
index 86d5de3..d2191b9 100755
--- a/src/compiler.cc
@@ -429,7 +535,7 @@ index 86d5de3..d2191b9 100755
diff --git a/src/compiler.h b/src/compiler.h
-index e75e869..ca4b62d 100644
+index e75e869..17cd369 100644
--- a/src/compiler.h
+++ b/src/compiler.h
@@ -54,6 +54,7 @@ class CompilationInfo BASE_EMBEDDED {
@@ -450,16 +556,14 @@ index e75e869..ca4b62d 100644
void MarkAsAllowingNativesSyntax() {
flags_ |= IsNativesSyntaxAllowed::encode(true);
}
-@@ -141,7 +145,8 @@ class CompilationInfo BASE_EMBEDDED {
+@@ -141,6 +145,7 @@ class CompilationInfo BASE_EMBEDDED {
// Determine whether or not we can adaptively optimize.
bool AllowOptimize() {
-- return V8::UseCrankshaft() && !closure_.is_null();
+ // XXX - fix qml mode optimizations
-+ return V8::UseCrankshaft() && !closure_.is_null() && !is_qml_mode();
+ return V8::UseCrankshaft() && !closure_.is_null();
}
- private:
@@ -163,8 +168,13 @@ class CompilationInfo BASE_EMBEDDED {
void Initialize(Mode mode) {
@@ -697,10 +801,10 @@ index d6ed1b9..e3241aa 100644
Scope* scope() { return info_->scope(); }
diff --git a/src/heap.cc b/src/heap.cc
-index 46df787..6e02262 100644
+index bf2940e..da958c2 100644
--- a/src/heap.cc
+++ b/src/heap.cc
-@@ -3792,6 +3792,7 @@ MaybeObject* Heap::AllocateFunctionContext(int length, JSFunction* function) {
+@@ -3795,6 +3795,7 @@ MaybeObject* Heap::AllocateFunctionContext(int length, JSFunction* function) {
context->set_previous(NULL);
context->set_extension(NULL);
context->set_global(function->context()->global());
@@ -708,7 +812,7 @@ index 46df787..6e02262 100644
ASSERT(!context->IsGlobalContext());
ASSERT(context->is_function_context());
ASSERT(result->IsContext());
-@@ -3814,6 +3815,7 @@ MaybeObject* Heap::AllocateWithContext(Context* previous,
+@@ -3817,6 +3818,7 @@ MaybeObject* Heap::AllocateWithContext(Context* previous,
context->set_previous(previous);
context->set_extension(extension);
context->set_global(previous->global());
@@ -716,6 +820,63 @@ index 46df787..6e02262 100644
ASSERT(!context->IsGlobalContext());
ASSERT(!context->is_function_context());
ASSERT(result->IsContext());
+diff --git a/src/hydrogen-instructions.h b/src/hydrogen-instructions.h
+index a623775..52455bc 100644
+--- a/src/hydrogen-instructions.h
++++ b/src/hydrogen-instructions.h
+@@ -1148,7 +1148,7 @@ class HOuterContext: public HUnaryOperation {
+
+ class HGlobalObject: public HUnaryOperation {
+ public:
+- explicit HGlobalObject(HValue* context) : HUnaryOperation(context) {
++ explicit HGlobalObject(HValue* context) : HUnaryOperation(context), qml_global_(false) {
+ set_representation(Representation::Tagged());
+ SetFlag(kUseGVN);
+ }
+@@ -1159,8 +1159,14 @@ class HGlobalObject: public HUnaryOperation {
+ return Representation::Tagged();
+ }
+
++ bool qml_global() { return qml_global_; }
++ void set_qml_global(bool v) { qml_global_ = v; }
++
+ protected:
+ virtual bool DataEquals(HValue* other) { return true; }
++
++ private:
++ bool qml_global_;
+ };
+
+
+@@ -1177,7 +1183,7 @@ class HGlobalReceiver: public HUnaryOperation {
+ virtual Representation RequiredInputRepresentation(int index) const {
+ return Representation::Tagged();
+ }
+-
++
+ protected:
+ virtual bool DataEquals(HValue* other) { return true; }
+ };
+diff --git a/src/hydrogen.cc b/src/hydrogen.cc
+index 73ea97d..d17e304 100644
+--- a/src/hydrogen.cc
++++ b/src/hydrogen.cc
+@@ -2918,6 +2918,7 @@ void HGraphBuilder::VisitVariableProxy(VariableProxy* expr) {
+ HContext* context = new(zone()) HContext;
+ AddInstruction(context);
+ HGlobalObject* global_object = new(zone()) HGlobalObject(context);
++ if (variable->is_qml_global()) global_object->set_qml_global(true);
+ AddInstruction(global_object);
+ HLoadGlobalGeneric* instr =
+ new(zone()) HLoadGlobalGeneric(context,
+@@ -3307,6 +3308,7 @@ void HGraphBuilder::HandleGlobalVariableAssignment(Variable* var,
+ HContext* context = new(zone()) HContext;
+ AddInstruction(context);
+ HGlobalObject* global_object = new(zone()) HGlobalObject(context);
++ if (var->is_qml_global()) global_object->set_qml_global(true);
+ AddInstruction(global_object);
+ HStoreGlobalGeneric* instr =
+ new(zone()) HStoreGlobalGeneric(context,
diff --git a/src/ia32/code-stubs-ia32.cc b/src/ia32/code-stubs-ia32.cc
index 5d32095..afa599e 100644
--- a/src/ia32/code-stubs-ia32.cc
@@ -735,10 +896,26 @@ index 5d32095..afa599e 100644
__ mov(ebx, factory->undefined_value());
for (int i = Context::MIN_CONTEXT_SLOTS; i < length; i++) {
diff --git a/src/ia32/full-codegen-ia32.cc b/src/ia32/full-codegen-ia32.cc
-index 5d153a8..28b78ba 100644
+index 5d153a8..0ddcde2 100644
--- a/src/ia32/full-codegen-ia32.cc
+++ b/src/ia32/full-codegen-ia32.cc
-@@ -1107,10 +1107,10 @@ void FullCodeGenerator::EmitLoadGlobalSlotCheckExtensions(
+@@ -142,12 +142,13 @@ void FullCodeGenerator::Generate(CompilationInfo* info) {
+
+ // Possibly allocate a local context.
+ int heap_slots = scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS;
+- if (heap_slots > 0) {
++ if (heap_slots > 0 ||
++ (scope()->is_qml_mode() && scope()->is_global_scope())) {
+ Comment cmnt(masm_, "[ Allocate local context");
+ // Argument to NewContext is the function, which is still in edi.
+ __ push(edi);
+ if (heap_slots <= FastNewContextStub::kMaximumSlots) {
+- FastNewContextStub stub(heap_slots);
++ FastNewContextStub stub((heap_slots < 0)?0:heap_slots);
+ __ CallStub(&stub);
+ } else {
+ __ CallRuntime(Runtime::kNewContext, 1);
+@@ -1107,10 +1108,10 @@ void FullCodeGenerator::EmitLoadGlobalSlotCheckExtensions(
// All extension objects were empty and it is safe to use a global
// load IC call.
@@ -751,7 +928,7 @@ index 5d153a8..28b78ba 100644
? RelocInfo::CODE_TARGET
: RelocInfo::CODE_TARGET_CONTEXT;
EmitCallIC(ic, mode);
-@@ -1214,10 +1214,10 @@ void FullCodeGenerator::EmitVariableLoad(Variable* var) {
+@@ -1214,10 +1215,10 @@ void FullCodeGenerator::EmitVariableLoad(Variable* var) {
Comment cmnt(masm_, "Global variable");
// Use inline caching. Variable name is passed in ecx and the global
// object on the stack.
@@ -764,7 +941,7 @@ index 5d153a8..28b78ba 100644
context()->Plug(eax);
} else if (slot != NULL && slot->type() == Slot::LOOKUP) {
-@@ -1837,11 +1837,11 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var,
+@@ -1837,11 +1838,11 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var,
// assignment. Right-hand-side value is passed in eax, variable name in
// ecx, and the global object on the stack.
__ mov(ecx, var->name());
@@ -778,7 +955,7 @@ index 5d153a8..28b78ba 100644
} else if (op == Token::INIT_CONST) {
// Like var declarations, const declarations are hoisted to function
-@@ -2113,9 +2113,12 @@ void FullCodeGenerator::EmitResolvePossiblyDirectEval(ResolveEvalFlag flag,
+@@ -2113,9 +2114,12 @@ void FullCodeGenerator::EmitResolvePossiblyDirectEval(ResolveEvalFlag flag,
// Push the strict mode flag.
__ push(Immediate(Smi::FromInt(strict_mode_flag())));
@@ -792,7 +969,7 @@ index 5d153a8..28b78ba 100644
}
-@@ -2188,8 +2191,8 @@ void FullCodeGenerator::VisitCall(Call* expr) {
+@@ -2188,8 +2192,8 @@ void FullCodeGenerator::VisitCall(Call* expr) {
context()->DropAndPlug(1, eax);
} else if (var != NULL && !var->is_this() && var->is_global()) {
// Push global object as receiver for the call IC.
@@ -803,6 +980,71 @@ index 5d153a8..28b78ba 100644
} else if (var != NULL && var->AsSlot() != NULL &&
var->AsSlot()->type() == Slot::LOOKUP) {
// Call to a lookup slot (dynamically introduced variable).
+diff --git a/src/ia32/lithium-codegen-ia32.cc b/src/ia32/lithium-codegen-ia32.cc
+index 0f96f78..c1da075 100644
+--- a/src/ia32/lithium-codegen-ia32.cc
++++ b/src/ia32/lithium-codegen-ia32.cc
+@@ -159,12 +159,13 @@ bool LCodeGen::GeneratePrologue() {
+
+ // Possibly allocate a local context.
+ int heap_slots = scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS;
+- if (heap_slots > 0) {
++ if (heap_slots > 0 ||
++ (scope()->is_qml_mode() && scope()->is_global_scope())) {
+ Comment(";;; Allocate local context");
+ // Argument to NewContext is the function, which is still in edi.
+ __ push(edi);
+ if (heap_slots <= FastNewContextStub::kMaximumSlots) {
+- FastNewContextStub stub(heap_slots);
++ FastNewContextStub stub((heap_slots < 0)?0:heap_slots);
+ __ CallStub(&stub);
+ } else {
+ __ CallRuntime(Runtime::kNewContext, 1);
+@@ -2525,7 +2526,7 @@ void LCodeGen::DoOuterContext(LOuterContext* instr) {
+ void LCodeGen::DoGlobalObject(LGlobalObject* instr) {
+ Register context = ToRegister(instr->context());
+ Register result = ToRegister(instr->result());
+- __ mov(result, Operand(context, Context::SlotOffset(Context::GLOBAL_INDEX)));
++ __ mov(result, Operand(context, Context::SlotOffset(instr->qml_global()?Context::QML_GLOBAL_INDEX:Context::GLOBAL_INDEX)));
+ }
+
+
+diff --git a/src/ia32/lithium-ia32.cc b/src/ia32/lithium-ia32.cc
+index 9ccd189..8e98b73 100644
+--- a/src/ia32/lithium-ia32.cc
++++ b/src/ia32/lithium-ia32.cc
+@@ -1205,7 +1205,7 @@ LInstruction* LChunkBuilder::DoOuterContext(HOuterContext* instr) {
+
+ LInstruction* LChunkBuilder::DoGlobalObject(HGlobalObject* instr) {
+ LOperand* context = UseRegisterAtStart(instr->value());
+- return DefineAsRegister(new LGlobalObject(context));
++ return DefineAsRegister(new LGlobalObject(context, instr->qml_global()));
+ }
+
+
+diff --git a/src/ia32/lithium-ia32.h b/src/ia32/lithium-ia32.h
+index 9ace8f8..95ed001 100644
+--- a/src/ia32/lithium-ia32.h
++++ b/src/ia32/lithium-ia32.h
+@@ -1416,13 +1416,17 @@ class LOuterContext: public LTemplateInstruction<1, 1, 0> {
+
+ class LGlobalObject: public LTemplateInstruction<1, 1, 0> {
+ public:
+- explicit LGlobalObject(LOperand* context) {
++ explicit LGlobalObject(LOperand* context, bool qml_global) {
+ inputs_[0] = context;
++ qml_global_ = qml_global;
+ }
+
+ DECLARE_CONCRETE_INSTRUCTION(GlobalObject, "global-object")
+
+ LOperand* context() { return InputAt(0); }
++ bool qml_global() { return qml_global_; }
++ private:
++ bool qml_global_;
+ };
+
+
diff --git a/src/ia32/macro-assembler-ia32.h b/src/ia32/macro-assembler-ia32.h
index b986264..f8479ae 100644
--- a/src/ia32/macro-assembler-ia32.h
@@ -820,10 +1062,10 @@ index b986264..f8479ae 100644
Operand ApiParameterOperand(int index);
diff --git a/src/objects-inl.h b/src/objects-inl.h
-index a205f02..8c0c2d0 100644
+index 231b835..1c7f83e 100644
--- a/src/objects-inl.h
+++ b/src/objects-inl.h
-@@ -3241,6 +3241,18 @@ void SharedFunctionInfo::set_strict_mode(bool value) {
+@@ -3242,6 +3242,18 @@ void SharedFunctionInfo::set_strict_mode(bool value) {
}
@@ -843,7 +1085,7 @@ index a205f02..8c0c2d0 100644
ACCESSORS(CodeCache, normal_type_cache, Object, kNormalTypeCacheOffset)
diff --git a/src/objects.h b/src/objects.h
-index 439ad1e..918ab61 100644
+index 1bdb5c7..edbc47a 100644
--- a/src/objects.h
+++ b/src/objects.h
@@ -4331,6 +4331,10 @@ class SharedFunctionInfo: public HeapObject {
@@ -1245,7 +1487,7 @@ index bf1ba68..5e97173 100644
F(OptimizeObjectForAddingMultipleProperties, 2, 1) \
\
diff --git a/src/scopes.cc b/src/scopes.cc
-index 8df93c5..e34e762 100644
+index 8df93c5..734a217 100644
--- a/src/scopes.cc
+++ b/src/scopes.cc
@@ -198,6 +198,7 @@ void Scope::SetDefaults(Type type,
@@ -1256,15 +1498,7 @@ index 8df93c5..e34e762 100644
outer_scope_calls_eval_ = false;
inner_scope_calls_eval_ = false;
outer_scope_is_eval_scope_ = false;
-@@ -516,6 +517,7 @@ bool Scope::HasTrivialContext() const {
- if (scope->is_eval_scope()) return false;
- if (scope->scope_inside_with_) return false;
- if (scope->num_heap_slots_ > 0) return false;
-+ if (scope->qml_mode_ && is_global_scope() && inner_scopes_.length()) return false;
- }
- return true;
- }
-@@ -796,6 +798,10 @@ void Scope::ResolveVariable(Scope* global_scope,
+@@ -796,6 +797,10 @@ void Scope::ResolveVariable(Scope* global_scope,
ASSERT(global_scope != NULL);
var = global_scope->DeclareGlobal(proxy->name());
@@ -1275,7 +1509,7 @@ index 8df93c5..e34e762 100644
} else if (scope_inside_with_) {
// If we are inside a with statement we give up and look up
// the variable at runtime.
-@@ -816,6 +822,8 @@ void Scope::ResolveVariable(Scope* global_scope,
+@@ -816,6 +821,8 @@ void Scope::ResolveVariable(Scope* global_scope,
// variables.
if (context->GlobalIfNotShadowedByEval(proxy->name())) {
var = NonLocal(proxy->name(), Variable::DYNAMIC_GLOBAL);
@@ -1284,7 +1518,7 @@ index 8df93c5..e34e762 100644
} else {
var = NonLocal(proxy->name(), Variable::DYNAMIC);
-@@ -827,6 +835,9 @@ void Scope::ResolveVariable(Scope* global_scope,
+@@ -827,6 +834,9 @@ void Scope::ResolveVariable(Scope* global_scope,
// variable is global unless it is shadowed by eval-introduced
// variables.
var = NonLocal(proxy->name(), Variable::DYNAMIC_GLOBAL);
@@ -1294,18 +1528,6 @@ index 8df93c5..e34e762 100644
}
}
}
-@@ -1112,6 +1123,11 @@ void Scope::AllocateVariablesRecursively() {
- must_have_local_context = is_function_scope();
- }
-
-+ if (qml_mode_ && is_global_scope() && inner_scopes_.length()) {
-+ must_have_local_context = true;
-+ num_heap_slots_++; // This is a hack to force a context to be allocated to save the QML global
-+ }
-+
- // If we didn't allocate any locals in the local context, then we only
- // need the minimal number of slots if we must have a local context.
- if (num_heap_slots_ == Context::MIN_CONTEXT_SLOTS &&
diff --git a/src/scopes.h b/src/scopes.h
index a0e56a4..6dd3f65 100644
--- a/src/scopes.h
@@ -1391,10 +1613,26 @@ index c365385..d923494 100644
__ LoadRoot(rbx, Heap::kUndefinedValueRootIndex);
for (int i = Context::MIN_CONTEXT_SLOTS; i < length; i++) {
diff --git a/src/x64/full-codegen-x64.cc b/src/x64/full-codegen-x64.cc
-index 97168cd..342fe9b 100644
+index 97168cd..c45cdb6 100644
--- a/src/x64/full-codegen-x64.cc
+++ b/src/x64/full-codegen-x64.cc
-@@ -1119,10 +1119,10 @@ void FullCodeGenerator::EmitLoadGlobalSlotCheckExtensions(
+@@ -141,12 +141,13 @@ void FullCodeGenerator::Generate(CompilationInfo* info) {
+
+ // Possibly allocate a local context.
+ int heap_slots = scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS;
+- if (heap_slots > 0) {
++ if (heap_slots > 0 ||
++ (scope()->is_qml_mode() && scope()->is_global_scope())) {
+ Comment cmnt(masm_, "[ Allocate local context");
+ // Argument to NewContext is the function, which is still in rdi.
+ __ push(rdi);
+ if (heap_slots <= FastNewContextStub::kMaximumSlots) {
+- FastNewContextStub stub(heap_slots);
++ FastNewContextStub stub((heap_slots < 0)?0:heap_slots);
+ __ CallStub(&stub);
+ } else {
+ __ CallRuntime(Runtime::kNewContext, 1);
+@@ -1119,10 +1120,10 @@ void FullCodeGenerator::EmitLoadGlobalSlotCheckExtensions(
// All extension objects were empty and it is safe to use a global
// load IC call.
@@ -1407,7 +1645,7 @@ index 97168cd..342fe9b 100644
? RelocInfo::CODE_TARGET
: RelocInfo::CODE_TARGET_CONTEXT;
EmitCallIC(ic, mode);
-@@ -1227,9 +1227,9 @@ void FullCodeGenerator::EmitVariableLoad(Variable* var) {
+@@ -1227,9 +1228,9 @@ void FullCodeGenerator::EmitVariableLoad(Variable* var) {
// Use inline caching. Variable name is passed in rcx and the global
// object on the stack.
__ Move(rcx, var->name());
@@ -1419,7 +1657,7 @@ index 97168cd..342fe9b 100644
context()->Plug(rax);
} else if (slot != NULL && slot->type() == Slot::LOOKUP) {
-@@ -1806,11 +1806,11 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var,
+@@ -1806,11 +1807,11 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var,
// assignment. Right-hand-side value is passed in rax, variable name in
// rcx, and the global object on the stack.
__ Move(rcx, var->name());
@@ -1433,7 +1671,7 @@ index 97168cd..342fe9b 100644
} else if (op == Token::INIT_CONST) {
// Like var declarations, const declarations are hoisted to function
-@@ -2085,9 +2085,12 @@ void FullCodeGenerator::EmitResolvePossiblyDirectEval(ResolveEvalFlag flag,
+@@ -2085,9 +2086,12 @@ void FullCodeGenerator::EmitResolvePossiblyDirectEval(ResolveEvalFlag flag,
// Push the strict mode flag.
__ Push(Smi::FromInt(strict_mode_flag()));
@@ -1447,7 +1685,7 @@ index 97168cd..342fe9b 100644
}
-@@ -2160,8 +2163,8 @@ void FullCodeGenerator::VisitCall(Call* expr) {
+@@ -2160,8 +2164,8 @@ void FullCodeGenerator::VisitCall(Call* expr) {
} else if (var != NULL && !var->is_this() && var->is_global()) {
// Call to a global variable.
// Push global object as receiver for the call IC lookup.
@@ -1458,6 +1696,66 @@ index 97168cd..342fe9b 100644
} else if (var != NULL && var->AsSlot() != NULL &&
var->AsSlot()->type() == Slot::LOOKUP) {
// Call to a lookup slot (dynamically introduced variable).
+diff --git a/src/x64/lithium-codegen-x64.cc b/src/x64/lithium-codegen-x64.cc
+index 202e7a2..45acbdf 100644
+--- a/src/x64/lithium-codegen-x64.cc
++++ b/src/x64/lithium-codegen-x64.cc
+@@ -174,12 +174,13 @@ bool LCodeGen::GeneratePrologue() {
+
+ // Possibly allocate a local context.
+ int heap_slots = scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS;
+- if (heap_slots > 0) {
++ if (heap_slots > 0 ||
++ (scope()->is_qml_mode() && scope()->is_global_scope())) {
+ Comment(";;; Allocate local context");
+ // Argument to NewContext is the function, which is still in rdi.
+ __ push(rdi);
+ if (heap_slots <= FastNewContextStub::kMaximumSlots) {
+- FastNewContextStub stub(heap_slots);
++ FastNewContextStub stub((heap_slots < 0)?0:heap_slots);
+ __ CallStub(&stub);
+ } else {
+ __ CallRuntime(Runtime::kNewContext, 1);
+@@ -2540,7 +2541,7 @@ void LCodeGen::DoOuterContext(LOuterContext* instr) {
+
+ void LCodeGen::DoGlobalObject(LGlobalObject* instr) {
+ Register result = ToRegister(instr->result());
+- __ movq(result, GlobalObjectOperand());
++ __ movq(result, instr->qml_global()?QmlGlobalObjectOperand():GlobalObjectOperand());
+ }
+
+
+diff --git a/src/x64/lithium-x64.cc b/src/x64/lithium-x64.cc
+index 07ca3a5..00feeac 100644
+--- a/src/x64/lithium-x64.cc
++++ b/src/x64/lithium-x64.cc
+@@ -1194,7 +1194,7 @@ LInstruction* LChunkBuilder::DoOuterContext(HOuterContext* instr) {
+
+
+ LInstruction* LChunkBuilder::DoGlobalObject(HGlobalObject* instr) {
+- return DefineAsRegister(new LGlobalObject);
++ return DefineAsRegister(new LGlobalObject(instr->qml_global()));
+ }
+
+
+diff --git a/src/x64/lithium-x64.h b/src/x64/lithium-x64.h
+index 15bb894..16f754c 100644
+--- a/src/x64/lithium-x64.h
++++ b/src/x64/lithium-x64.h
+@@ -1365,7 +1365,13 @@ class LOuterContext: public LTemplateInstruction<1, 1, 0> {
+
+ class LGlobalObject: public LTemplateInstruction<1, 0, 0> {
+ public:
++ explicit LGlobalObject(bool qml_global) : qml_global_(qml_global) {}
++
+ DECLARE_CONCRETE_INSTRUCTION(GlobalObject, "global-object")
++
++ bool qml_global() { return qml_global_; }
++ private:
++ bool qml_global_;
+ };
+
+
diff --git a/src/x64/macro-assembler-x64.h b/src/x64/macro-assembler-x64.h
index 4c17720..aa284ed 100644
--- a/src/x64/macro-assembler-x64.h
diff --git a/src/v8/0006-Allow-access-to-the-calling-script-data.patch b/src/v8/0006-Allow-access-to-the-calling-script-data.patch
index cc4fbabf73..214fe823c1 100644
--- a/src/v8/0006-Allow-access-to-the-calling-script-data.patch
+++ b/src/v8/0006-Allow-access-to-the-calling-script-data.patch
@@ -1,7 +1,7 @@
-From bbf7e31aa48416f43efbff97eb84b89954fa6607 Mon Sep 17 00:00:00 2001
+From 55ac15fff18ba2d0469c92c533e7ceb1c343fcd9 Mon Sep 17 00:00:00 2001
From: Aaron Kennedy <aaron.kennedy@nokia.com>
Date: Wed, 25 May 2011 10:36:13 +1000
-Subject: [PATCH 6/7] Allow access to the calling script data
+Subject: [PATCH 6/8] Allow access to the calling script data
---
include/v8.h | 1 +
@@ -9,10 +9,10 @@ Subject: [PATCH 6/7] Allow access to the calling script data
2 files changed, 13 insertions(+), 0 deletions(-)
diff --git a/include/v8.h b/include/v8.h
-index a67feb2..6577a30 100644
+index d04b73e..5f9e725 100644
--- a/include/v8.h
+++ b/include/v8.h
-@@ -3312,6 +3312,7 @@ class V8EXPORT Context {
+@@ -3335,6 +3335,7 @@ class V8EXPORT Context {
*/
static Local<Context> GetCalling();
static Local<Object> GetCallingQmlGlobal();
@@ -21,10 +21,10 @@ index a67feb2..6577a30 100644
/**
* Sets the security token for the context. To access an object in
diff --git a/src/api.cc b/src/api.cc
-index 61ed79e..f2fb371 100644
+index 0635f34..ba487e8 100644
--- a/src/api.cc
+++ b/src/api.cc
-@@ -3961,6 +3961,18 @@ v8::Local<v8::Object> Context::GetCallingQmlGlobal() {
+@@ -3972,6 +3972,18 @@ v8::Local<v8::Object> Context::GetCallingQmlGlobal() {
}
}
diff --git a/src/v8/0007-Fix-warnings.patch b/src/v8/0007-Fix-warnings.patch
index 5292ae0b8a..1b7da91217 100644
--- a/src/v8/0007-Fix-warnings.patch
+++ b/src/v8/0007-Fix-warnings.patch
@@ -1,17 +1,17 @@
-From f7c8bc0d210ba97fad3261c5581f48221610f503 Mon Sep 17 00:00:00 2001
+From d37bb342f33c384e912ec7d86dfda8f384253ddd 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 7/7] Fix warnings
+Subject: [PATCH 7/8] Fix warnings
---
include/v8.h | 16 ++++++++--------
1 files changed, 8 insertions(+), 8 deletions(-)
diff --git a/include/v8.h b/include/v8.h
-index 6577a30..3e1f520 100644
+index 5f9e725..255b90b 100644
--- a/include/v8.h
+++ b/include/v8.h
-@@ -2391,7 +2391,7 @@ class V8EXPORT Extension { // NOLINT
+@@ -2414,7 +2414,7 @@ class V8EXPORT Extension { // NOLINT
const char** deps = 0);
virtual ~Extension() { }
virtual v8::Handle<v8::FunctionTemplate>
@@ -20,7 +20,7 @@ index 6577a30..3e1f520 100644
return v8::Handle<v8::FunctionTemplate>();
}
-@@ -3697,13 +3697,13 @@ class Internals {
+@@ -3720,13 +3720,13 @@ class Internals {
return *reinterpret_cast<T*>(addr);
}
diff --git a/src/v8/0008-Add-custom-object-compare-callback.patch b/src/v8/0008-Add-custom-object-compare-callback.patch
new file mode 100644
index 0000000000..ecc6eaa56d
--- /dev/null
+++ b/src/v8/0008-Add-custom-object-compare-callback.patch
@@ -0,0 +1,489 @@
+From eb2dadf516823ec342e6d75a3a78b2af7b1dea85 Mon Sep 17 00:00:00 2001
+From: Aaron Kennedy <aaron.kennedy@nokia.com>
+Date: Mon, 27 Jun 2011 14:57:28 +1000
+Subject: [PATCH 8/8] 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 | 19 +++++++++++++++++++
+ src/arm/code-stubs-arm.cc | 42 ++++++++++++++++++++++++++++++++++++++++--
+ src/factory.cc | 8 ++++++++
+ src/ia32/code-stubs-ia32.cc | 40 ++++++++++++++++++++++++++++++++++++++++
+ src/isolate.h | 8 ++++++++
+ src/objects-inl.h | 15 +++++++++++++++
+ src/objects.h | 10 +++++++++-
+ src/runtime.cc | 23 +++++++++++++++++++++++
+ src/runtime.h | 1 +
+ src/top.cc | 5 +++++
+ src/x64/code-stubs-x64.cc | 37 +++++++++++++++++++++++++++++++++++++
+ 12 files changed, 218 insertions(+), 3 deletions(-)
+
+diff --git a/include/v8.h b/include/v8.h
+index 255b90b..52a5839 100644
+--- a/include/v8.h
++++ b/include/v8.h
+@@ -2364,6 +2364,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);
+@@ -2564,6 +2570,10 @@ typedef void (*FailedAccessCheckCallback)(Local<Object> target,
+ AccessType type,
+ Local<Value> data);
+
++// --- U s e r O b j e c t C o m p a r i s o n C a l l b a c k ---
++typedef bool (*UserObjectComparisonCallback)(Local<Object> lhs,
++ Local<Object> rhs);
++
+ // --- G a r b a g e C o l l e c t i o n C a l l b a c k s
+
+ /**
+@@ -2814,6 +2824,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 ba487e8..930f338 100644
+--- a/src/api.cc
++++ b/src/api.cc
+@@ -1321,6 +1321,16 @@ 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 ---
+
+@@ -4628,6 +4638,15 @@ 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 a2626bf..749c9be 100644
+--- a/src/arm/code-stubs-arm.cc
++++ b/src/arm/code-stubs-arm.cc
+@@ -1563,6 +1563,36 @@ void CompareStub::Generate(MacroAssembler* masm) {
+ // NOTICE! This code is only reached after a smi-fast-case check, so
+ // it is certain that at least one operand isn't a smi.
+
++ {
++ Label not_user_equal, user_equal;
++ __ and_(r2, r1, Operand(r0));
++ __ tst(r2, Operand(kSmiTagMask));
++ __ b(eq, &not_user_equal);
++
++ __ CompareObjectType(r0, r2, r4, JS_OBJECT_TYPE);
++ __ b(ne, &not_user_equal);
++
++ __ CompareObjectType(r1, r3, r4, JS_OBJECT_TYPE);
++ __ b(ne, &not_user_equal);
++
++ __ ldrb(r2, FieldMemOperand(r2, Map::kBitField3Offset));
++ __ and_(r2, r2, Operand(1 << Map::kUseUserObjectComparison));
++ __ cmp(r2, Operand(1 << Map::kUseUserObjectComparison));
++ __ b(eq, &user_equal);
++
++ __ ldrb(r3, FieldMemOperand(r3, Map::kBitField3Offset));
++ __ and_(r3, r3, Operand(1 << Map::kUseUserObjectComparison));
++ __ cmp(r3, Operand(1 << Map::kUseUserObjectComparison));
++ __ b(ne, &not_user_equal);
++
++ __ bind(&user_equal);
++
++ __ Push(r0, r1);
++ __ TailCallRuntime(Runtime::kUserObjectEquals, 2, 1);
++
++ __ bind(&not_user_equal);
++ }
++
+ // Handle the case where the objects are identical. Either returns the answer
+ // or goes to slow. Only falls through if the objects were not identical.
+ EmitIdenticalObjectComparison(masm, &slow, cc_, never_nan_nan_);
+@@ -5802,10 +5832,18 @@ void ICCompareStub::GenerateObjects(MacroAssembler* masm) {
+ __ tst(r2, Operand(kSmiTagMask));
+ __ b(eq, &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::kBitField3Offset));
++ __ 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::kBitField3Offset));
++ __ 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 d530a75..6f8c7de 100644
+--- a/src/factory.cc
++++ b/src/factory.cc
+@@ -998,6 +998,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 =
+@@ -1007,6 +1008,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;
+@@ -1051,6 +1054,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 afa599e..0964ab9 100644
+--- a/src/ia32/code-stubs-ia32.cc
++++ b/src/ia32/code-stubs-ia32.cc
+@@ -3447,6 +3447,40 @@ void CompareStub::Generate(MacroAssembler* masm) {
+ __ Assert(not_zero, "Unexpected smi operands.");
+ }
+
++ {
++ NearLabel not_user_equal, user_equal;
++ __ test(eax, Immediate(kSmiTagMask));
++ __ j(zero, &not_user_equal);
++ __ test(edx, Immediate(kSmiTagMask));
++ __ j(zero, &not_user_equal);
++
++ __ CmpObjectType(eax, JS_OBJECT_TYPE, ebx);
++ __ j(not_equal, &not_user_equal);
++
++ __ CmpObjectType(edx, JS_OBJECT_TYPE, ecx);
++ __ j(not_equal, &not_user_equal);
++
++ __ test_b(FieldOperand(ebx, Map::kBitField3Offset),
++ 1 << Map::kUseUserObjectComparison);
++ __ j(not_zero, &user_equal);
++ __ test_b(FieldOperand(ecx, Map::kBitField3Offset),
++ 1 << Map::kUseUserObjectComparison);
++ __ j(not_zero, &user_equal);
++
++ __ jmp(&not_user_equal);
++
++ __ bind(&user_equal);
++
++ __ pop(ebx); // Return address.
++ __ push(eax);
++ __ push(edx);
++ __ push(ebx);
++ __ TailCallRuntime(Runtime::kUserObjectEquals, 2, 1);
++
++ __ bind(&not_user_equal);
++ }
++
++
+ // 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.
+
+@@ -5592,8 +5626,14 @@ void ICCompareStub::GenerateObjects(MacroAssembler* masm) {
+
+ __ CmpObjectType(eax, JS_OBJECT_TYPE, ecx);
+ __ j(not_equal, &miss, not_taken);
++ __ test_b(FieldOperand(ecx, Map::kBitField3Offset),
++ 1 << Map::kUseUserObjectComparison);
++ __ j(not_zero, &miss);
+ __ CmpObjectType(edx, JS_OBJECT_TYPE, ecx);
+ __ j(not_equal, &miss, not_taken);
++ __ test_b(FieldOperand(ecx, Map::kBitField3Offset),
++ 1 << Map::kUseUserObjectComparison);
++ __ j(not_zero, &miss);
+
+ ASSERT(GetCondition() == equal);
+ __ sub(eax, Operand(edx));
+diff --git a/src/isolate.h b/src/isolate.h
+index 35ffcb4..8130397 100644
+--- a/src/isolate.h
++++ b/src/isolate.h
+@@ -267,6 +267,9 @@ class ThreadLocalTop BASE_EMBEDDED {
+ // Call back function to report unsafe JS accesses.
+ v8::FailedAccessCheckCallback failed_access_check_callback_;
+
++ // Call back function for user object comparisons
++ v8::UserObjectComparisonCallback user_object_comparison_callback_;
++
+ private:
+ void InitializeInternal();
+
+@@ -699,6 +702,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 1c7f83e..1765441 100644
+--- a/src/objects-inl.h
++++ b/src/objects-inl.h
+@@ -2552,6 +2552,19 @@ bool Map::has_external_resource()
+ }
+
+
++void Map::set_use_user_object_comparison(bool value) {
++ if (value) {
++ set_bit_field3(bit_field3() | (1 << kUseUserObjectComparison));
++ } else {
++ set_bit_field3(bit_field3() & ~(1 << kUseUserObjectComparison));
++ }
++}
++
++bool Map::use_user_object_comparison() {
++ return ((1 << kUseUserObjectComparison) & bit_field3()) != 0;
++}
++
++
+ void Map::set_named_interceptor_is_fallback(bool value)
+ {
+ if (value) {
+@@ -3050,6 +3063,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.h b/src/objects.h
+index edbc47a..e75e9f1 100644
+--- a/src/objects.h
++++ b/src/objects.h
+@@ -3724,6 +3724,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();
+
+ // Whether the named interceptor is a fallback interceptor or not
+ inline void set_named_interceptor_is_fallback(bool value);
+@@ -3922,6 +3927,7 @@ class Map: public HeapObject {
+ // Bit positions for bit field 3
+ static const int kNamedInterceptorIsFallback = 0;
+ static const int kHasExternalResource = 1;
++ static const int kUseUserObjectComparison = 2;
+
+ // Layout of the default cache. It holds alternating name and code objects.
+ static const int kCodeCacheEntrySize = 2;
+@@ -6442,6 +6448,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);
+
+@@ -6459,7 +6466,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 827d954..d552ddb 100644
+--- a/src/runtime.cc
++++ b/src/runtime.cc
+@@ -6279,6 +6279,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 5e97173..0d754f9 100644
+--- a/src/runtime.h
++++ b/src/runtime.h
+@@ -146,6 +146,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/top.cc b/src/top.cc
+index e078ee9..c345383 100644
+--- a/src/top.cc
++++ b/src/top.cc
+@@ -68,6 +68,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;
+ }
+@@ -387,6 +388,10 @@ 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/x64/code-stubs-x64.cc b/src/x64/code-stubs-x64.cc
+index d923494..10b9b56 100644
+--- a/src/x64/code-stubs-x64.cc
++++ b/src/x64/code-stubs-x64.cc
+@@ -2443,6 +2443,37 @@ void CompareStub::Generate(MacroAssembler* masm) {
+ __ bind(&ok);
+ }
+
++ {
++ NearLabel not_user_equal, user_equal;
++ __ JumpIfSmi(rax, &not_user_equal);
++ __ JumpIfSmi(rdx, &not_user_equal);
++
++ __ CmpObjectType(rax, JS_OBJECT_TYPE, rbx);
++ __ j(not_equal, &not_user_equal);
++
++ __ CmpObjectType(rdx, JS_OBJECT_TYPE, rcx);
++ __ j(not_equal, &not_user_equal);
++
++ __ testb(FieldOperand(rbx, Map::kBitField3Offset),
++ Immediate(1 << Map::kUseUserObjectComparison));
++ __ j(not_zero, &user_equal);
++ __ testb(FieldOperand(rcx, Map::kBitField3Offset),
++ Immediate(1 << Map::kUseUserObjectComparison));
++ __ j(not_zero, &user_equal);
++
++ __ jmp(&not_user_equal);
++
++ __ bind(&user_equal);
++
++ __ pop(rbx); // Return address.
++ __ push(rax);
++ __ push(rdx);
++ __ push(rbx);
++ __ TailCallRuntime(Runtime::kUserObjectEquals, 2, 1);
++
++ __ bind(&not_user_equal);
++ }
++
+ // The compare stub returns a positive, negative, or zero 64-bit integer
+ // value in rax, corresponding to result of comparing the two inputs.
+ // NOTICE! This code is only reached after a smi-fast-case check, so
+@@ -4471,8 +4502,14 @@ void ICCompareStub::GenerateObjects(MacroAssembler* masm) {
+
+ __ CmpObjectType(rax, JS_OBJECT_TYPE, rcx);
+ __ j(not_equal, &miss, not_taken);
++ __ testb(FieldOperand(rcx, Map::kBitField3Offset),
++ Immediate(1 << Map::kUseUserObjectComparison));
++ __ j(not_zero, &miss);
+ __ CmpObjectType(rdx, JS_OBJECT_TYPE, rcx);
+ __ j(not_equal, &miss, not_taken);
++ __ testb(FieldOperand(rcx, Map::kBitField3Offset),
++ Immediate(1 << Map::kUseUserObjectComparison));
++ __ j(not_zero, &miss);
+
+ ASSERT(GetCondition() == equal);
+ __ subq(rax, rdx);
+--
+1.7.2.3
+