diff options
author | Aaron Kennedy <aaron.kennedy@nokia.com> | 2011-10-11 15:06:25 +1000 |
---|---|---|
committer | Qt by Nokia <qt-info@nokia.com> | 2011-10-19 20:48:25 +0200 |
commit | 7dc5973bf12919d2d35230844beabe558d4faa00 (patch) | |
tree | 88d6128a911d2ec3b9a72d8e45d56fc2b250c714 | |
parent | 4dc25c1f2995a5e02da47f0f6f3522af9eb6f78c (diff) |
Update V8
Change-Id: I7a9da7dbb2116a441788407d60ed10155cded941
Reviewed-by: Kent Hansen <kent.hansen@nokia.com>
24 files changed, 1567 insertions, 2702 deletions
diff --git a/src/3rdparty/v8 b/src/3rdparty/v8 -Subproject 8f15248619bb3bf49473dc3ede8a4e631bd5d19 +Subproject 9c0d93bfae724e29ef63456942d9ddca10ca582 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 8a844f5f25..d74624b285 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,25 +1,25 @@ -From 3dff2e903674d8ab5310d44281b57de36db659c9 Mon Sep 17 00:00:00 2001 +From b0b5bcfbda218aac8e797c19ff6f6de4052d972f 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 01/16] Add hashing and comparison methods to v8::String +Date: Tue, 4 Oct 2011 15:04:21 +1000 +Subject: [PATCH 01/11] Add hashing and comparison methods to v8::String -This allows us to more rapidly search for a v8::String inside -a hash of QStrings. +This allows us to more rapidly search for a v8::String inside a hash +of QStrings. --- - include/v8.h | 45 +++++++++++++++++++++++++++++++ - src/api.cc | 43 +++++++++++++++++++++++++++++ + 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 | 77 ++++++++++++++++++++++++++++++++++++++++++++++++++++- - src/objects.h | 15 +++++++++- - 7 files changed, 183 insertions(+), 3 deletions(-) + 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 d15d024..be1ee71 100644 +index 73b7fbe..86ea70f 100644 --- a/include/v8.h +++ b/include/v8.h -@@ -994,6 +994,49 @@ class String : public Primitive { +@@ -1021,6 +1021,49 @@ class String : public Primitive { V8EXPORT int Utf8Length() const; /** @@ -69,29 +69,30 @@ index d15d024..be1ee71 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 +1066,8 @@ class String : public Primitive { - HINT_MANY_WRITES_EXPECTED = 1 +@@ -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, - int length = -1, diff --git a/src/api.cc b/src/api.cc -index a2373cd..381935b 100644 +index 7ae01d1..2d205fd 100644 --- a/src/api.cc +++ b/src/api.cc -@@ -3284,6 +3284,49 @@ int String::Utf8Length() const { - return str->Utf8Length(); +@@ -3652,6 +3652,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(); @@ -103,40 +104,47 @@ index a2373cd..381935b 100644 + 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 99737ed..f4fce7b 100644 +index 4bd893e..a4dfa5a 100644 --- a/src/heap-inl.h +++ b/src/heap-inl.h -@@ -93,6 +93,7 @@ MaybeObject* Heap::AllocateAsciiSymbol(Vector<const char> str, +@@ -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); @@ -144,7 +152,7 @@ index 99737ed..f4fce7b 100644 ASSERT_EQ(size, answer->Size()); -@@ -126,6 +127,7 @@ MaybeObject* Heap::AllocateTwoByteSymbol(Vector<const uc16> str, +@@ -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); @@ -153,18 +161,18 @@ index 99737ed..f4fce7b 100644 ASSERT_EQ(size, answer->Size()); diff --git a/src/heap.cc b/src/heap.cc -index 2b6c11f..930c97b 100644 +index 522861d..0dfd453 100644 --- a/src/heap.cc +++ b/src/heap.cc -@@ -3519,6 +3519,7 @@ MaybeObject* Heap::AllocateInternalSymbol(unibrow::CharacterStream* buffer, +@@ -4061,6 +4061,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); ++ SeqString::cast(answer)->set_symbol_id(0); ASSERT_EQ(size, answer->Size()); -@@ -3561,6 +3562,7 @@ MaybeObject* Heap::AllocateRawAsciiString(int length, PretenureFlag pretenure) { +@@ -4103,6 +4104,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); @@ -172,7 +180,7 @@ index 2b6c11f..930c97b 100644 ASSERT_EQ(size, HeapObject::cast(result)->Size()); return result; } -@@ -3596,6 +3598,7 @@ MaybeObject* Heap::AllocateRawTwoByteString(int length, +@@ -4138,6 +4140,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); @@ -181,11 +189,11 @@ index 2b6c11f..930c97b 100644 return result; } diff --git a/src/objects-inl.h b/src/objects-inl.h -index 65aec5d..c82080d 100644 +index baf271f..73d0ac9 100644 --- a/src/objects-inl.h +++ b/src/objects-inl.h -@@ -1924,6 +1924,7 @@ INT_ACCESSORS(ExternalArray, length, kLengthOffset) - +@@ -2192,6 +2192,7 @@ SMI_ACCESSORS(FixedArrayBase, length, kLengthOffset) + SMI_ACCESSORS(FreeSpace, size, kSizeOffset) SMI_ACCESSORS(String, length, kLengthOffset) +SMI_ACCESSORS(SeqString, symbol_id, kSymbolIdOffset) @@ -193,13 +201,13 @@ index 65aec5d..c82080d 100644 uint32_t String::hash_field() { diff --git a/src/objects.cc b/src/objects.cc -index df61956..dc4b260 100644 +index 45ae49d..fe5bf97 100644 --- a/src/objects.cc +++ b/src/objects.cc -@@ -5346,6 +5346,66 @@ static inline bool CompareStringContentsPartial(Isolate* isolate, - } +@@ -6242,6 +6242,71 @@ static inline bool CompareStringContentsPartial(Isolate* isolate, } + +bool String::SlowEqualsExternal(uc16 *string, int length) { + int len = this->length(); + if (len != length) return false; @@ -212,13 +220,14 @@ index df61956..dc4b260 100644 + String* lhs = this->TryFlattenGetString(); + + if (lhs->IsFlat()) { ++ String::FlatContent lhs_content = lhs->GetFlatContent(); + if (lhs->IsAsciiRepresentation()) { -+ Vector<const char> vec1 = lhs->ToAsciiVector(); ++ 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->ToUC16Vector(); ++ Vector<const uc16> vec1 = lhs_content.ToUC16Vector(); + Vector<const uc16> vec2(string, length); + return CompareRawStringContents(vec1, vec2); + } @@ -230,6 +239,7 @@ index df61956..dc4b260 100644 + } +} + ++ +bool String::SlowEqualsExternal(char *string, int length) +{ + int len = this->length(); @@ -249,10 +259,11 @@ index df61956..dc4b260 100644 + } + + if (lhs->IsFlat()) { -+ Vector<const uc16> vec1 = lhs->ToUC16Vector(); -+ VectorIterator<const uc16> buf1(vec1); -+ VectorIterator<char> buf2(string, length); -+ return CompareStringContents(&buf1, &buf2); ++ 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); @@ -260,10 +271,12 @@ index df61956..dc4b260 100644 + return CompareStringContents(isolate->objects_string_compare_buffer_a(), &ib); + } +} - ++ ++ bool String::SlowEquals(String* other) { // Fast check: negative check with lengths. -@@ -8655,9 +8715,24 @@ class AsciiSymbolKey : public SequentialSymbolKey<char> { + int len = length(); +@@ -10103,9 +10168,24 @@ class AsciiSymbolKey : public SequentialSymbolKey<char> { MaybeObject* AsObject() { if (hash_field_ == 0) Hash(); @@ -288,12 +301,12 @@ index df61956..dc4b260 100644 +Atomic32 AsciiSymbolKey::next_symbol_id = 1; - class TwoByteSymbolKey : public SequentialSymbolKey<uc16> { + class SubStringAsciiSymbolKey : public HashTableKey { diff --git a/src/objects.h b/src/objects.h -index e966b3d..6e26f57 100644 +index 5a1a4a3..eb4eb0e 100644 --- a/src/objects.h +++ b/src/objects.h -@@ -5359,6 +5359,9 @@ class String: public HeapObject { +@@ -5952,6 +5952,9 @@ class String: public HeapObject { bool IsAsciiEqualTo(Vector<const char> str); bool IsTwoByteEqualTo(Vector<const uc16> str); @@ -303,42 +316,21 @@ index e966b3d..6e26f57 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: +@@ -6207,8 +6210,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); + - // 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); ++ static const int kSymbolIdOffset = String::kSize; ++ static const int kHeaderSize = kSymbolIdOffset + kPointerSize; - // Maximal memory usage for a single sequential two-byte string. + // Shortcuts for templates that know their string-type exactly. + bool IsExternalAsciiString() { -- 1.7.4.4 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 deleted file mode 100644 index 59dbad3135..0000000000 --- a/src/v8/0002-Add-a-bit-field-3-to-Map.patch +++ /dev/null @@ -1,118 +0,0 @@ -From 01f7bd262fb1be893fe4bdc6b98a1b43c5a0bb7d 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 02/16] Add a bit field 3 to Map - -Bit field 3 will be used to add QML specific map flags. ---- - src/heap.cc | 2 ++ - src/objects-inl.h | 10 ++++++++++ - src/objects.cc | 2 ++ - src/objects.h | 9 ++++++++- - 4 files changed, 22 insertions(+), 1 deletions(-) - -diff --git a/src/heap.cc b/src/heap.cc -index 930c97b..900f462 100644 ---- a/src/heap.cc -+++ b/src/heap.cc -@@ -1573,6 +1573,7 @@ MaybeObject* Heap::AllocatePartialMap(InstanceType instance_type, - reinterpret_cast<Map*>(result)->set_unused_property_fields(0); - reinterpret_cast<Map*>(result)->set_bit_field(0); - reinterpret_cast<Map*>(result)->set_bit_field2(0); -+ reinterpret_cast<Map*>(result)->set_bit_field3(0); - return result; - } - -@@ -1599,6 +1600,7 @@ MaybeObject* Heap::AllocateMap(InstanceType instance_type, int instance_size) { - map->set_unused_property_fields(0); - map->set_bit_field(0); - map->set_bit_field2((1 << Map::kIsExtensible) | (1 << Map::kHasFastElements)); -+ map->set_bit_field3(0); - - // 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 c82080d..cce3edd 100644 ---- a/src/objects-inl.h -+++ b/src/objects-inl.h -@@ -2430,6 +2430,16 @@ void Map::set_bit_field2(byte value) { - } - - -+byte Map::bit_field3() { -+ return READ_BYTE_FIELD(this, kBitField3Offset); -+} -+ -+ -+void Map::set_bit_field3(byte value) { -+ WRITE_BYTE_FIELD(this, kBitField3Offset, value); -+} -+ -+ - void Map::set_non_instance_prototype(bool value) { - if (value) { - set_bit_field(bit_field() | (1 << kHasNonInstancePrototype)); -diff --git a/src/objects.cc b/src/objects.cc -index dc4b260..79d7240 100644 ---- a/src/objects.cc -+++ b/src/objects.cc -@@ -3614,6 +3614,7 @@ MaybeObject* Map::CopyDropDescriptors() { - } - Map::cast(result)->set_bit_field(bit_field()); - Map::cast(result)->set_bit_field2(bit_field2()); -+ Map::cast(result)->set_bit_field3(bit_field3()); - Map::cast(result)->set_is_shared(false); - Map::cast(result)->ClearCodeCache(heap); - return result; -@@ -3642,6 +3643,7 @@ MaybeObject* Map::CopyNormalized(PropertyNormalizationMode mode, - - Map::cast(result)->set_bit_field(bit_field()); - Map::cast(result)->set_bit_field2(bit_field2()); -+ Map::cast(result)->set_bit_field3(bit_field3()); - - Map::cast(result)->set_is_shared(sharing == SHARED_NORMALIZED_MAP); - -diff --git a/src/objects.h b/src/objects.h -index 6e26f57..07e1089 100644 ---- a/src/objects.h -+++ b/src/objects.h -@@ -3597,6 +3597,10 @@ class Map: public HeapObject { - inline byte bit_field2(); - inline void set_bit_field2(byte value); - -+ // Bit field 3. -+ inline byte bit_field3(); -+ inline void set_bit_field3(byte value); -+ - // Tells whether the object in the prototype property will be used - // for instances created from this function. If the prototype - // property is set to a value that is not a JSObject, the prototype -@@ -3844,7 +3848,7 @@ class Map: public HeapObject { - // Layout description. - static const int kInstanceSizesOffset = HeapObject::kHeaderSize; - static const int kInstanceAttributesOffset = kInstanceSizesOffset + kIntSize; -- static const int kPrototypeOffset = kInstanceAttributesOffset + kIntSize; -+ static const int kPrototypeOffset = POINTER_SIZE_ALIGN(kInstanceAttributesOffset + 2 * kIntSize); - static const int kConstructorOffset = kPrototypeOffset + kPointerSize; - static const int kInstanceDescriptorsOffset = - kConstructorOffset + kPointerSize; -@@ -3876,6 +3880,7 @@ class Map: public HeapObject { - static const int kUnusedPropertyFieldsOffset = kInstanceAttributesOffset + 1; - static const int kBitFieldOffset = kInstanceAttributesOffset + 2; - static const int kBitField2Offset = kInstanceAttributesOffset + 3; -+ static const int kBitField3Offset = kInstanceAttributesOffset + 4; - - STATIC_CHECK(kInstanceTypeOffset == Internals::kMapInstanceTypeOffset); - -@@ -3898,6 +3903,8 @@ class Map: public HeapObject { - static const int kIsShared = 5; - static const int kHasExternalArrayElements = 6; - -+ // Bit positions for bit field 3 -+ - // Layout of the default cache. It holds alternating name and code objects. - static const int kCodeCacheEntrySize = 2; - static const int kCodeCacheEntryNameOffset = 0; --- -1.7.4.4 - diff --git a/src/v8/0003-Add-a-fallback-mode-for-named-property-interceptors.patch b/src/v8/0002-Add-a-fallback-mode-for-named-property-interceptors.patch index 78184f6f9d..af42f1555f 100644 --- a/src/v8/0003-Add-a-fallback-mode-for-named-property-interceptors.patch +++ b/src/v8/0002-Add-a-fallback-mode-for-named-property-interceptors.patch @@ -1,7 +1,7 @@ -From 530ded6ea634bccb96652cd3e0cf67725449ed63 Mon Sep 17 00:00:00 2001 +From a80d89daacb698b72f59cad5b83c1f1633a98c9f 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 03/16] Add a "fallback" mode for named property interceptors +Date: Tue, 4 Oct 2011 15:30:20 +1000 +Subject: [PATCH 02/11] 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 @@ -12,22 +12,22 @@ 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 | 8 ++++++++ + include/v8.h | 7 +++++++ src/api.cc | 29 +++++++++++++++++++++++++++++ - src/factory.cc | 4 ++++ + src/factory.cc | 3 +++ src/handles.cc | 6 ++++-- src/handles.h | 3 ++- - src/objects-inl.h | 16 ++++++++++++++++ - src/objects.cc | 22 ++++++++++++++++------ - src/objects.h | 18 ++++++++++++++---- + src/objects-inl.h | 15 +++++++++++++++ + src/objects.cc | 24 +++++++++++++++++------- + src/objects.h | 16 ++++++++++++---- src/runtime.cc | 11 ++++++----- - 9 files changed, 99 insertions(+), 18 deletions(-) + 9 files changed, 95 insertions(+), 19 deletions(-) diff --git a/include/v8.h b/include/v8.h -index be1ee71..bb31ea0 100644 +index 86ea70f..d2e6c32 100644 --- a/include/v8.h +++ b/include/v8.h -@@ -2170,6 +2170,7 @@ class V8EXPORT FunctionTemplate : public Template { +@@ -2305,6 +2305,7 @@ class V8EXPORT FunctionTemplate : public Template { NamedPropertyQuery query, NamedPropertyDeleter remover, NamedPropertyEnumerator enumerator, @@ -35,25 +35,24 @@ index be1ee71..bb31ea0 100644 Handle<Value> data); void SetIndexedInstancePropertyHandler(IndexedPropertyGetter getter, IndexedPropertySetter setter, -@@ -2254,6 +2255,13 @@ class V8EXPORT ObjectTemplate : public Template { +@@ -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 381935b..8b0b32a 100644 +index 2d205fd..e4dd694 100644 --- a/src/api.cc +++ b/src/api.cc -@@ -981,6 +981,7 @@ void FunctionTemplate::SetNamedInstancePropertyHandler( +@@ -1123,6 +1123,7 @@ void FunctionTemplate::SetNamedInstancePropertyHandler( NamedPropertyQuery query, NamedPropertyDeleter remover, NamedPropertyEnumerator enumerator, @@ -61,7 +60,7 @@ index 381935b..8b0b32a 100644 Handle<Value> data) { i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); if (IsDeadCheck(isolate, -@@ -999,6 +1000,7 @@ void FunctionTemplate::SetNamedInstancePropertyHandler( +@@ -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); @@ -69,7 +68,7 @@ index 381935b..8b0b32a 100644 if (data.IsEmpty()) data = v8::Undefined(); obj->set_data(*Utils::OpenHandle(*data)); -@@ -1143,6 +1145,33 @@ void ObjectTemplate::SetNamedPropertyHandler(NamedPropertyGetter getter, +@@ -1285,6 +1287,33 @@ void ObjectTemplate::SetNamedPropertyHandler(NamedPropertyGetter getter, query, remover, enumerator, @@ -85,7 +84,7 @@ index 381935b..8b0b32a 100644 + NamedPropertyEnumerator enumerator, + Handle<Value> data) { + i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); -+ if (IsDeadCheck(isolate, "v8::ObjectTemplate::SetFallbackPropertyHandler()")) { ++ if (IsDeadCheck(isolate, "v8::ObjectTemplate::SetNamedPropertyHandler()")) { + return; + } + ENTER_V8(isolate); @@ -104,14 +103,13 @@ index 381935b..8b0b32a 100644 } diff --git a/src/factory.cc b/src/factory.cc -index 7dee66f..dcdc645 100644 +index 00fc6bb..2338cda 100644 --- a/src/factory.cc +++ b/src/factory.cc -@@ -1058,6 +1058,10 @@ Handle<JSFunction> Factory::CreateApiFunction( +@@ -1180,6 +1180,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); @@ -119,10 +117,10 @@ index 7dee66f..dcdc645 100644 if (!obj->indexed_property_handler()->IsUndefined()) { map->set_has_indexed_interceptor(); diff --git a/src/handles.cc b/src/handles.cc -index 326de86..dd3a86c 100644 +index ce4258d..104fc9c 100644 --- a/src/handles.cc +++ b/src/handles.cc -@@ -262,9 +262,11 @@ Handle<Object> SetProperty(Handle<JSObject> object, +@@ -265,9 +265,11 @@ Handle<Object> SetProperty(Handle<JSReceiver> object, Handle<String> key, Handle<Object> value, PropertyAttributes attributes, @@ -137,10 +135,10 @@ index 326de86..dd3a86c 100644 } diff --git a/src/handles.h b/src/handles.h -index 3839f37..4b42506 100644 +index 8dcca3e..babe763 100644 --- a/src/handles.h +++ b/src/handles.h -@@ -188,7 +188,8 @@ Handle<Object> SetProperty(Handle<JSObject> object, +@@ -192,7 +192,8 @@ Handle<Object> SetProperty(Handle<JSReceiver> object, Handle<String> key, Handle<Object> value, PropertyAttributes attributes, @@ -151,13 +149,14 @@ 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 cce3edd..6aaca2f 100644 +index 73d0ac9..35fbea5 100644 --- a/src/objects-inl.h +++ b/src/objects-inl.h -@@ -2521,6 +2521,21 @@ bool Map::is_shared() { +@@ -2864,6 +2864,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) { @@ -171,12 +170,10 @@ index cce3edd..6aaca2f 100644 +{ + return ((1 << kNamedInterceptorIsFallback) & bit_field3()) != 0; +} -+ -+ + + JSFunction* Map::unchecked_constructor() { - return reinterpret_cast<JSFunction*>(READ_FIELD(this, kConstructorOffset)); - } -@@ -2970,6 +2985,7 @@ ACCESSORS(InterceptorInfo, query, Object, kQueryOffset) +@@ -3350,6 +3364,7 @@ ACCESSORS(InterceptorInfo, query, Object, kQueryOffset) ACCESSORS(InterceptorInfo, deleter, Object, kDeleterOffset) ACCESSORS(InterceptorInfo, enumerator, Object, kEnumeratorOffset) ACCESSORS(InterceptorInfo, data, Object, kDataOffset) @@ -185,71 +182,73 @@ index cce3edd..6aaca2f 100644 ACCESSORS(CallHandlerInfo, callback, Object, kCallbackOffset) ACCESSORS(CallHandlerInfo, data, Object, kDataOffset) diff --git a/src/objects.cc b/src/objects.cc -index 79d7240..15e2cdb 100644 +index fe5bf97..8e1773f 100644 --- a/src/objects.cc +++ b/src/objects.cc -@@ -1712,9 +1712,10 @@ MaybeObject* JSObject::SetPropertyWithInterceptor( - MaybeObject* JSObject::SetProperty(String* name, - Object* value, - PropertyAttributes attributes, -- StrictModeFlag strict_mode) { -+ StrictModeFlag strict_mode, -+ bool skip_fallback_interceptor) { +@@ -1838,9 +1838,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; - LocalLookup(name, &result); + LocalLookup(name, &result, skip_fallback_interceptor); return SetProperty(&result, name, value, attributes, strict_mode); } -@@ -3148,7 +3149,8 @@ AccessorDescriptor* Map::FindAccessor(String* name) { +@@ -3832,7 +3833,8 @@ AccessorDescriptor* Map::FindAccessor(String* name) { } --void JSObject::LocalLookup(String* name, LookupResult* result) { -+void JSObject::LocalLookup(String* name, LookupResult* result, -+ bool skip_fallback_interceptor) { +-void JSReceiver::LocalLookup(String* name, LookupResult* result) { ++void JSReceiver::LocalLookup(String* name, LookupResult* result, ++ bool skip_fallback_interceptor) { ASSERT(name->IsString()); Heap* heap = GetHeap(); -@@ -3174,22 +3176,30 @@ void JSObject::LocalLookup(String* name, LookupResult* result) { +@@ -3864,23 +3866,31 @@ void JSReceiver::LocalLookup(String* name, LookupResult* result) { } // Check for lookup interceptor except when bootstrapping. -- if (HasNamedInterceptor() && !heap->isolate()->bootstrapper()->IsActive()) { -+ bool wouldIntercept = HasNamedInterceptor() && !heap->isolate()->bootstrapper()->IsActive(); +- 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(this); + result->InterceptorResult(js_object); return; } - LocalLookupRealNamedProperty(name, result); + js_object->LocalLookupRealNamedProperty(name, result); + -+ if (wouldIntercept && !skip_fallback_interceptor && !result->IsProperty() && ++ if (wouldIntercept && !skip_fallback_interceptor && !result->IsProperty() && + map()->named_interceptor_is_fallback()) { -+ result->InterceptorResult(this); ++ result->InterceptorResult(js_object); + return; + } } --void JSObject::Lookup(String* name, LookupResult* result) { -+void JSObject::Lookup(String* name, LookupResult* result, -+ bool skip_fallback_interceptor) { +-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()) { -- JSObject::cast(current)->LocalLookup(name, result); -+ JSObject::cast(current)->LocalLookup(name, result, skip_fallback_interceptor); +- 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 07e1089..a209cd0 100644 +index eb4eb0e..b974756 100644 --- a/src/objects.h +++ b/src/objects.h -@@ -1405,7 +1405,8 @@ class JSObject: public HeapObject { +@@ -1332,7 +1332,8 @@ class JSReceiver: public HeapObject { MUST_USE_RESULT MaybeObject* SetProperty(String* key, Object* value, PropertyAttributes attributes, @@ -259,7 +258,7 @@ index 07e1089..a209cd0 100644 MUST_USE_RESULT MaybeObject* SetProperty(LookupResult* result, String* key, Object* value, -@@ -1637,8 +1638,8 @@ class JSObject: public HeapObject { +@@ -1381,8 +1382,8 @@ class JSReceiver: public HeapObject { // Lookup a property. If found, the result is valid and has // detailed information. @@ -268,30 +267,28 @@ index 07e1089..a209cd0 100644 + void LocalLookup(String* name, LookupResult* result, bool skip_fallback_interceptor = false); + void Lookup(String* name, LookupResult* result, bool skip_fallback_interceptor = false); - // The following lookup functions skip interceptors. - void LocalLookupRealNamedProperty(String* name, LookupResult* result); -@@ -3714,6 +3715,12 @@ class Map: public HeapObject { + protected: + Smi* GenerateIdentityHash(); +@@ -4071,6 +4072,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) -@@ -3904,6 +3911,7 @@ class Map: public HeapObject { - static const int kHasExternalArrayElements = 6; +@@ -4307,6 +4312,7 @@ class Map: public HeapObject { // Bit positions for bit field 3 -+ static const int kNamedInterceptorIsFallback = 0; + 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; -@@ -6276,6 +6284,7 @@ class InterceptorInfo: public Struct { +@@ -7142,6 +7148,7 @@ class InterceptorInfo: public Struct { DECL_ACCESSORS(deleter, Object) DECL_ACCESSORS(enumerator, Object) DECL_ACCESSORS(data, Object) @@ -299,7 +296,7 @@ index 07e1089..a209cd0 100644 static inline InterceptorInfo* cast(Object* obj); -@@ -6295,7 +6304,8 @@ class InterceptorInfo: public Struct { +@@ -7161,7 +7168,8 @@ class InterceptorInfo: public Struct { static const int kDeleterOffset = kQueryOffset + kPointerSize; static const int kEnumeratorOffset = kDeleterOffset + kPointerSize; static const int kDataOffset = kEnumeratorOffset + kPointerSize; @@ -310,48 +307,48 @@ index 07e1089..a209cd0 100644 private: DISALLOW_IMPLICIT_CONSTRUCTORS(InterceptorInfo); diff --git a/src/runtime.cc b/src/runtime.cc -index 7335da8..660352c 100644 +index 89abf38..5a850e9 100644 --- a/src/runtime.cc +++ b/src/runtime.cc -@@ -1097,7 +1097,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareGlobals) { +@@ -1236,7 +1236,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; - global->Lookup(*name, &lookup); + global->Lookup(*name, &lookup, true); if (lookup.IsProperty()) { - // Determine if the property is local by comparing the holder - // against the global object. The information will be used to -@@ -1152,7 +1152,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareGlobals) { + // We found an existing property. Unless it was an interceptor + // that claims the property is absent, skip this declaration. +@@ -1263,7 +1263,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareGlobals) { } LookupResult lookup; - global->LocalLookup(*name, &lookup); + global->LocalLookup(*name, &lookup, true); - PropertyAttributes attributes = is_const_property - ? static_cast<PropertyAttributes>(base | READ_ONLY) -@@ -1196,7 +1196,8 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareGlobals) { + // Compute the property attributes. According to ECMA-262, section + // 13, page 71, the property must be read-only and +@@ -1306,7 +1306,8 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareGlobals) { name, value, - attributes, + static_cast<PropertyAttributes>(attr), - strict_mode)); + strict_mode, + true)); } } -@@ -1343,7 +1344,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeVarGlobal) { - JSObject* real_holder = global; - LookupResult lookup; - while (true) { -- real_holder->LocalLookup(*name, &lookup); -+ real_holder->LocalLookup(*name, &lookup, true); - if (lookup.IsProperty()) { - // Determine if this is a redeclaration of something read-only. - if (lookup.IsReadOnly()) { -@@ -1400,7 +1401,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeVarGlobal) { - +@@ -1442,7 +1443,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); +@@ -1465,7 +1466,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); diff --git a/src/v8/0003-Generalize-external-object-resources.patch b/src/v8/0003-Generalize-external-object-resources.patch new file mode 100644 index 0000000000..658a09126a --- /dev/null +++ b/src/v8/0003-Generalize-external-object-resources.patch @@ -0,0 +1,595 @@ +From be5bc4e5ea15dd74c2753c30c25a4660598274c3 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/11] 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 e4dd694..85f0d4b 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 --- + + +@@ -4031,6 +4059,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 2338cda..e3cccae 100644 +--- a/src/factory.cc ++++ b/src/factory.cc +@@ -1119,15 +1119,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: +@@ -1162,6 +1168,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 a4dfa5a..b121d01 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; + } + + +@@ -556,6 +571,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]; +@@ -584,14 +609,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); + Verify(); + } +diff --git a/src/heap.cc b/src/heap.cc +index 0dfd453..c730455 100644 +--- a/src/heap.cc ++++ b/src/heap.cc +@@ -1095,18 +1095,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()); + } + + +@@ -1122,11 +1122,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. +@@ -1134,12 +1134,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)); + } + + +@@ -6426,6 +6426,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 4a1e01d..bab4c63 100644 +--- a/src/heap.h ++++ b/src/heap.h +@@ -243,8 +243,8 @@ class Isolate; + class WeakObjectRetainer; + + +-typedef String* (*ExternalStringTableUpdaterCallback)(Heap* heap, +- Object** pointer); ++typedef HeapObject* (*ExternalStringTableUpdaterCallback)(Heap* heap, ++ Object** pointer); + + class StoreBufferRebuilder { + public: +@@ -329,10 +329,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); + +@@ -350,10 +354,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. +@@ -849,7 +853,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. +@@ -1662,7 +1666,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 e90a23d..b9ae787 100644 +--- a/src/mark-compact.cc ++++ b/src/mark-compact.cc +@@ -1521,8 +1521,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(); +@@ -2515,15 +2516,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 35fbea5..36af868 100644 +--- a/src/objects-inl.h ++++ b/src/objects-inl.h +@@ -1488,7 +1488,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); + } + + +@@ -1518,6 +1518,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. +@@ -2865,6 +2882,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) { +@@ -3396,6 +3427,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 b974756..dea5bbd 100644 +--- a/src/objects.h ++++ b/src/objects.h +@@ -1732,6 +1732,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); +@@ -4003,11 +4006,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); +@@ -4076,6 +4079,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) + +@@ -4288,7 +4296,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 +@@ -4313,6 +4321,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; +@@ -7292,6 +7301,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); + +@@ -7308,7 +7318,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.4 + diff --git a/src/v8/0004-Generalize-external-object-resources.patch b/src/v8/0004-Generalize-external-object-resources.patch deleted file mode 100644 index ece0f197d8..0000000000 --- a/src/v8/0004-Generalize-external-object-resources.patch +++ /dev/null @@ -1,894 +0,0 @@ -From f9368b52060c31e9532ef26f6cca1a2cb0283f51 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 04/16] 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 | 64 ++++++++++++++- - src/extensions/externalize-string-extension.cc | 4 +- - src/factory.cc | 11 +++ - src/heap-inl.h | 101 +++++++++++++++--------- - src/heap.cc | 68 ++++++++-------- - src/heap.h | 42 +++++----- - src/liveobjectlist.cc | 4 +- - src/mark-compact.cc | 21 +++--- - src/objects-inl.h | 41 +++++++++- - src/objects.h | 14 +++- - 11 files changed, 280 insertions(+), 115 deletions(-) - -diff --git a/include/v8.h b/include/v8.h -index bb31ea0..205e856 100644 ---- a/include/v8.h -+++ b/include/v8.h -@@ -1631,6 +1631,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 HasRealNamedProperty(Handle<String> key); - V8EXPORT bool HasRealIndexedProperty(uint32_t index); -@@ -2332,6 +2351,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 8b0b32a..1a6fbbb 100644 ---- a/src/api.cc -+++ b/src/api.cc -@@ -1294,6 +1294,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 --- - - -@@ -3652,6 +3680,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()->NewProxy(static_cast<i::Address>((void *)resource))); -+ } -+ if (!obj->IsSymbol()) { -+ isolate->heap()->external_resource_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->IsProxy()) { -+ return reinterpret_cast<v8::Object::ExternalResource*>(i::Proxy::cast(value)->proxy()); -+ } else { -+ return NULL; -+ } -+} -+ -+ - // --- E n v i r o n m e n t --- - - -@@ -4144,7 +4200,7 @@ Local<String> v8::String::NewExternal( - LOG_API(isolate, "String::NewExternal"); - ENTER_V8(isolate); - i::Handle<i::String> result = NewExternalStringHandle(isolate, resource); -- isolate->heap()->external_string_table()->AddString(*result); -+ isolate->heap()->external_resource_table()->AddString(*result); - return Utils::ToLocal(result); - } - -@@ -4162,7 +4218,7 @@ bool v8::String::MakeExternal(v8::String::ExternalStringResource* resource) { - } - bool result = obj->MakeExternal(resource); - if (result && !obj->IsSymbol()) { -- isolate->heap()->external_string_table()->AddString(*obj); -+ isolate->heap()->external_resource_table()->AddString(*obj); - } - return result; - } -@@ -4175,7 +4231,7 @@ Local<String> v8::String::NewExternal( - LOG_API(isolate, "String::NewExternal"); - ENTER_V8(isolate); - i::Handle<i::String> result = NewExternalAsciiStringHandle(isolate, resource); -- isolate->heap()->external_string_table()->AddString(*result); -+ isolate->heap()->external_resource_table()->AddString(*result); - return Utils::ToLocal(result); - } - -@@ -4194,7 +4250,7 @@ bool v8::String::MakeExternal( - } - bool result = obj->MakeExternal(resource); - if (result && !obj->IsSymbol()) { -- isolate->heap()->external_string_table()->AddString(*obj); -+ isolate->heap()->external_resource_table()->AddString(*obj); - } - return result; - } -diff --git a/src/extensions/externalize-string-extension.cc b/src/extensions/externalize-string-extension.cc -index b3f83fe..8e50904 100644 ---- a/src/extensions/externalize-string-extension.cc -+++ b/src/extensions/externalize-string-extension.cc -@@ -100,7 +100,7 @@ v8::Handle<v8::Value> ExternalizeStringExtension::Externalize( - data, string->length()); - result = string->MakeExternal(resource); - if (result && !string->IsSymbol()) { -- HEAP->external_string_table()->AddString(*string); -+ HEAP->external_resource_table()->AddString(*string); - } - if (!result) delete resource; - } else { -@@ -110,7 +110,7 @@ v8::Handle<v8::Value> ExternalizeStringExtension::Externalize( - data, string->length()); - result = string->MakeExternal(resource); - if (result && !string->IsSymbol()) { -- HEAP->external_string_table()->AddString(*string); -+ HEAP->external_resource_table()->AddString(*string); - } - if (!result) delete resource; - } -diff --git a/src/factory.cc b/src/factory.cc -index dcdc645..d530a75 100644 ---- a/src/factory.cc -+++ b/src/factory.cc -@@ -997,15 +997,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: -@@ -1040,6 +1046,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 f4fce7b..58e7adf 100644 ---- a/src/heap-inl.h -+++ b/src/heap-inl.h -@@ -205,21 +205,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; -+ // 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->IsProxy()) { -+ resource = reinterpret_cast<v8::Object::ExternalResource*>(Proxy::cast(value)->proxy()); -+ } -+ if (resource) { -+ resource->Dispose(); -+ } -+ } - } - - -@@ -556,53 +571,63 @@ inline bool Heap::allow_allocation(bool new_state) { - #endif - - --void ExternalStringTable::AddString(String* string) { -- ASSERT(string->IsExternalString()); -+void ExternalResourceTable::AddString(String* string) { -+ ASSERT(string->IsExternalString() ); - if (heap_->InNewSpace(string)) { -- new_space_strings_.Add(string); -+ new_space_objects_.Add(string); -+ } else { -+ old_space_objects_.Add(string); -+ } -+} -+ -+ -+void ExternalResourceTable::AddObject(HeapObject* object) { -+ ASSERT(object->map()->has_external_resource()); -+ if (heap_->InNewSpace(object)) { -+ new_space_objects_.Add(object); - } else { -- old_space_strings_.Add(string); -+ old_space_objects_.Add(object); - } - } - - --void ExternalStringTable::Iterate(ObjectVisitor* v) { -- if (!new_space_strings_.is_empty()) { -- Object** start = &new_space_strings_[0]; -- v->VisitPointers(start, start + new_space_strings_.length()); -+void ExternalResourceTable::Iterate(ObjectVisitor* v) { -+ if (!new_space_objects_.is_empty()) { -+ Object** start = &new_space_objects_[0]; -+ v->VisitPointers(start, start + new_space_objects_.length()); - } -- if (!old_space_strings_.is_empty()) { -- Object** start = &old_space_strings_[0]; -- v->VisitPointers(start, start + old_space_strings_.length()); -+ if (!old_space_objects_.is_empty()) { -+ Object** start = &old_space_objects_[0]; -+ v->VisitPointers(start, start + old_space_objects_.length()); - } - } - - - // Verify() is inline to avoid ifdef-s around its calls in release - // mode. --void ExternalStringTable::Verify() { -+void ExternalResourceTable::Verify() { - #ifdef DEBUG -- for (int i = 0; i < new_space_strings_.length(); ++i) { -- ASSERT(heap_->InNewSpace(new_space_strings_[i])); -- ASSERT(new_space_strings_[i] != HEAP->raw_unchecked_null_value()); -+ for (int i = 0; i < new_space_objects_.length(); ++i) { -+ ASSERT(heap_->InNewSpace(new_space_objects_[i])); -+ ASSERT(new_space_objects_[i] != HEAP->raw_unchecked_null_value()); - } -- for (int i = 0; i < old_space_strings_.length(); ++i) { -- ASSERT(!heap_->InNewSpace(old_space_strings_[i])); -- ASSERT(old_space_strings_[i] != HEAP->raw_unchecked_null_value()); -+ for (int i = 0; i < old_space_objects_.length(); ++i) { -+ ASSERT(!heap_->InNewSpace(old_space_objects_[i])); -+ ASSERT(old_space_objects_[i] != HEAP->raw_unchecked_null_value()); - } - #endif - } - - --void ExternalStringTable::AddOldString(String* string) { -- ASSERT(string->IsExternalString()); -- ASSERT(!heap_->InNewSpace(string)); -- old_space_strings_.Add(string); -+void ExternalResourceTable::AddOldObject(HeapObject* object) { -+ ASSERT(object->IsExternalString() || object->map()->has_external_resource()); -+ ASSERT(!heap_->InNewSpace(object)); -+ old_space_objects_.Add(object); - } - - --void ExternalStringTable::ShrinkNewStrings(int position) { -- new_space_strings_.Rewind(position); -+void ExternalResourceTable::ShrinkNewObjects(int position) { -+ new_space_objects_.Rewind(position); - Verify(); - } - -diff --git a/src/heap.cc b/src/heap.cc -index 900f462..bf2940e 100644 ---- a/src/heap.cc -+++ b/src/heap.cc -@@ -155,7 +155,7 @@ Heap::Heap() - memset(roots_, 0, sizeof(roots_[0]) * kRootListLength); - global_contexts_list_ = NULL; - mark_compact_collector_.heap_ = this; -- external_string_table_.heap_ = this; -+ external_resource_table_.heap_ = this; - } - - -@@ -1030,8 +1030,8 @@ void Heap::Scavenge() { - - new_space_front = DoScavenge(&scavenge_visitor, new_space_front); - -- UpdateNewSpaceReferencesInExternalStringTable( -- &UpdateNewSpaceReferenceInExternalStringTableEntry); -+ UpdateNewSpaceReferencesInExternalResourceTable( -+ &UpdateNewSpaceReferenceInExternalResourceTableEntry); - - LiveObjectList::UpdateReferencesForScavengeGC(); - isolate()->runtime_profiler()->UpdateSamplesAfterScavenge(); -@@ -1053,38 +1053,38 @@ void Heap::Scavenge() { - } - - --String* Heap::UpdateNewSpaceReferenceInExternalStringTableEntry(Heap* heap, -- Object** p) { -+HeapObject* Heap::UpdateNewSpaceReferenceInExternalResourceTableEntry(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()); - } - - --void Heap::UpdateNewSpaceReferencesInExternalStringTable( -- ExternalStringTableUpdaterCallback updater_func) { -- external_string_table_.Verify(); -+void Heap::UpdateNewSpaceReferencesInExternalResourceTable( -+ ExternalResourceTableUpdaterCallback updater_func) { -+ external_resource_table_.Verify(); - -- if (external_string_table_.new_space_strings_.is_empty()) return; -+ if (external_resource_table_.new_space_objects_.is_empty()) return; - -- Object** start = &external_string_table_.new_space_strings_[0]; -- Object** end = start + external_string_table_.new_space_strings_.length(); -+ Object** start = &external_resource_table_.new_space_objects_[0]; -+ Object** end = start + external_resource_table_.new_space_objects_.length(); - Object** last = start; - - 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. -@@ -1092,12 +1092,12 @@ void Heap::UpdateNewSpaceReferencesInExternalStringTable( - ++last; - } else { - // String got promoted. Move it to the old string list. -- external_string_table_.AddOldString(target); -+ external_resource_table_.AddOldObject(target); - } - } - - ASSERT(last <= end); -- external_string_table_.ShrinkNewStrings(static_cast<int>(last - start)); -+ external_resource_table_.ShrinkNewObjects(static_cast<int>(last - start)); - } - - -@@ -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. -- external_string_table_.Iterate(v); -+ external_resource_table_.Iterate(v); - } - v->Synchronize("external_string_table"); - } -@@ -4970,7 +4970,7 @@ void Heap::TearDown() { - - isolate_->global_handles()->TearDown(); - -- external_string_table_.TearDown(); -+ external_resource_table_.TearDown(); - - new_space_.TearDown(); - -@@ -5835,31 +5835,31 @@ void TranscendentalCache::Clear() { - } - - --void ExternalStringTable::CleanUp() { -+void ExternalResourceTable::CleanUp() { - int last = 0; -- for (int i = 0; i < new_space_strings_.length(); ++i) { -- if (new_space_strings_[i] == heap_->raw_unchecked_null_value()) continue; -- if (heap_->InNewSpace(new_space_strings_[i])) { -- new_space_strings_[last++] = new_space_strings_[i]; -+ for (int i = 0; i < new_space_objects_.length(); ++i) { -+ if (new_space_objects_[i] == heap_->raw_unchecked_null_value()) continue; -+ if (heap_->InNewSpace(new_space_objects_[i])) { -+ new_space_objects_[last++] = new_space_objects_[i]; - } else { -- old_space_strings_.Add(new_space_strings_[i]); -+ old_space_objects_.Add(new_space_objects_[i]); - } - } -- new_space_strings_.Rewind(last); -+ new_space_objects_.Rewind(last); - last = 0; -- for (int i = 0; i < old_space_strings_.length(); ++i) { -- if (old_space_strings_[i] == heap_->raw_unchecked_null_value()) continue; -- ASSERT(!heap_->InNewSpace(old_space_strings_[i])); -- old_space_strings_[last++] = old_space_strings_[i]; -+ for (int i = 0; i < old_space_objects_.length(); ++i) { -+ if (old_space_objects_[i] == heap_->raw_unchecked_null_value()) continue; -+ ASSERT(!heap_->InNewSpace(old_space_objects_[i])); -+ old_space_objects_[last++] = old_space_objects_[i]; - } -- old_space_strings_.Rewind(last); -+ old_space_objects_.Rewind(last); - Verify(); - } - - --void ExternalStringTable::TearDown() { -- new_space_strings_.Free(); -- old_space_strings_.Free(); -+void ExternalResourceTable::TearDown() { -+ new_space_objects_.Free(); -+ old_space_objects_.Free(); - } - - -diff --git a/src/heap.h b/src/heap.h -index ae4e9e7..8cbf378 100644 ---- a/src/heap.h -+++ b/src/heap.h -@@ -237,8 +237,8 @@ class Isolate; - class WeakObjectRetainer; - - --typedef String* (*ExternalStringTableUpdaterCallback)(Heap* heap, -- Object** pointer); -+typedef HeapObject* (*ExternalResourceTableUpdaterCallback)(Heap* heap, -+ Object** pointer); - - typedef bool (*DirtyRegionCallback)(Heap* heap, - Address start, -@@ -284,43 +284,45 @@ class PromotionQueue { - }; - - --// External strings table is a place where all external strings are --// registered. We need to keep track of such strings to properly --// finalize them. --class ExternalStringTable { -+// External resource table is a place where all external strings and -+// objects with an external resource are registered. We need to keep -+// track of such strings to properly finalize them. -+class ExternalResourceTable { - public: - // Registers an external string. - inline void AddString(String* string); -+ // Registers an external object. -+ inline void AddObject(HeapObject* object); - - inline void Iterate(ObjectVisitor* v); - - // Restores internal invariant and gets rid of collected strings. -- // Must be called after each Iterate() that modified the strings. -+ // Must be called after each Iterate() that modified the objects. - void CleanUp(); - - // Destroys all allocated memory. - void TearDown(); - - private: -- ExternalStringTable() { } -+ ExternalResourceTable() { } - - friend class Heap; - - inline void Verify(); - -- inline void AddOldString(String* string); -+ inline void AddOldObject(HeapObject* object); - - // 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. -- List<Object*> new_space_strings_; -- List<Object*> old_space_strings_; -+ List<Object*> new_space_objects_; -+ List<Object*> old_space_objects_; - - Heap* heap_; - -- DISALLOW_COPY_AND_ASSIGN(ExternalStringTable); -+ DISALLOW_COPY_AND_ASSIGN(ExternalResourceTable); - }; - - -@@ -753,7 +755,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. -@@ -1191,8 +1193,8 @@ class Heap { - survived_since_last_expansion_ += survived; - } - -- void UpdateNewSpaceReferencesInExternalStringTable( -- ExternalStringTableUpdaterCallback updater_func); -+ void UpdateNewSpaceReferencesInExternalResourceTable( -+ ExternalResourceTableUpdaterCallback updater_func); - - void ProcessWeakReferences(WeakObjectRetainer* retainer); - -@@ -1228,8 +1230,8 @@ class Heap { - return &mark_compact_collector_; - } - -- ExternalStringTable* external_string_table() { -- return &external_string_table_; -+ ExternalResourceTable* external_resource_table() { -+ return &external_resource_table_; - } - - inline Isolate* isolate(); -@@ -1462,7 +1464,7 @@ class Heap { - // Performs a minor collection in new generation. - void Scavenge(); - -- static String* UpdateNewSpaceReferenceInExternalStringTableEntry( -+ static HeapObject* UpdateNewSpaceReferenceInExternalResourceTableEntry( - Heap* heap, - Object** pointer); - -@@ -1593,7 +1595,7 @@ class Heap { - // configured through the API until it is setup. - bool configured_; - -- ExternalStringTable external_string_table_; -+ ExternalResourceTable external_resource_table_; - - bool is_safe_to_read_maps_; - -diff --git a/src/liveobjectlist.cc b/src/liveobjectlist.cc -index 5795a6b..8866e58 100644 ---- a/src/liveobjectlist.cc -+++ b/src/liveobjectlist.cc -@@ -1989,7 +1989,7 @@ Object* LiveObjectList::PrintObj(int obj_id) { - ASSERT(resource->IsAscii()); - Handle<String> dump_string = - Factory::NewExternalStringFromAscii(resource); -- ExternalStringTable::AddString(*dump_string); -+ ExternalResourceTable::AddString(*dump_string); - return *dump_string; - } else { - delete resource; -@@ -2193,7 +2193,7 @@ Object* LiveObjectList::GetPathPrivate(HeapObject* obj1, HeapObject* obj2) { - ASSERT(resource->IsAscii()); - Handle<String> path_string = - Factory::NewExternalStringFromAscii(resource); -- ExternalStringTable::AddString(*path_string); -+ ExternalResourceTable::AddString(*path_string); - return *path_string; - } else { - delete resource; -diff --git a/src/mark-compact.cc b/src/mark-compact.cc -index 68a5062..775f787 100644 ---- a/src/mark-compact.cc -+++ b/src/mark-compact.cc -@@ -163,7 +163,7 @@ void MarkCompactCollector::Finish() { - // objects (empty string, illegal builtin). - heap()->isolate()->stub_cache()->Clear(); - -- heap()->external_string_table_.CleanUp(); -+ heap()->external_resource_table_.CleanUp(); - - // If we've just compacted old space there's no reason to check the - // fragmentation limit. Just return. -@@ -1019,8 +1019,9 @@ class SymbolTableCleaner : public ObjectVisitor { - - // Since no objects have yet been moved we can safely access the map of - // the object. -- if ((*p)->IsExternalString()) { -- heap_->FinalizeExternalString(String::cast(*p)); -+ if ((*p)->IsExternalString() || -+ ((*p)->IsHeapObject() && HeapObject::cast(*p)->map()->has_external_resource())) { -+ heap_->FinalizeExternalString(HeapObject::cast(*p)); - } - // Set the entry to null_value (as deleted). - *p = heap_->raw_unchecked_null_value(); -@@ -1433,8 +1434,8 @@ void MarkCompactCollector::MarkLiveObjects() { - SymbolTableCleaner v(heap()); - symbol_table->IterateElements(&v); - symbol_table->ElementsRemoved(v.PointersRemoved()); -- heap()->external_string_table_.Iterate(&v); -- heap()->external_string_table_.CleanUp(); -+ heap()->external_resource_table_.Iterate(&v); -+ heap()->external_resource_table_.CleanUp(); - - // Process the weak references. - MarkCompactWeakObjectRetainer mark_compact_object_retainer; -@@ -1948,11 +1949,11 @@ static void UpdatePointerToNewGen(HeapObject** p) { - } - - --static String* UpdateNewSpaceReferenceInExternalStringTableEntry(Heap* heap, -- Object** p) { -+static HeapObject* UpdateNewSpaceReferenceInExternalResourceTableEntry(Heap* heap, -+ Object** p) { - Address old_addr = HeapObject::cast(*p)->address(); - Address new_addr = Memory::Address_at(old_addr); -- return String::cast(HeapObject::FromAddress(new_addr)); -+ return HeapObject::FromAddress(new_addr); - } - - -@@ -2083,8 +2084,8 @@ static void SweepNewSpace(Heap* heap, NewSpace* space) { - updating_visitor.VisitPointer(heap->global_contexts_list_address()); - - // Update pointers from external string table. -- heap->UpdateNewSpaceReferencesInExternalStringTable( -- &UpdateNewSpaceReferenceInExternalStringTableEntry); -+ heap->UpdateNewSpaceReferencesInExternalResourceTable( -+ &UpdateNewSpaceReferenceInExternalResourceTableEntry); - - // 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 6aaca2f..231b835 100644 ---- a/src/objects-inl.h -+++ b/src/objects-inl.h -@@ -1392,13 +1392,13 @@ 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; - } - - - int JSObject::GetInternalFieldOffset(int index) { - ASSERT(index < GetInternalFieldCount() && index >= 0); -- return GetHeaderSize() + (kPointerSize * index); -+ return GetHeaderSize() + (kPointerSize * (index + map()->has_external_resource()?1:0)); - } - - -@@ -1407,7 +1407,7 @@ Object* JSObject::GetInternalField(int index) { - // Internal objects do follow immediately after the header, whereas in-object - // properties are at the end of the object. Therefore there is no need - // to adjust the index here. -- return READ_FIELD(this, GetHeaderSize() + (kPointerSize * index)); -+ return READ_FIELD(this, GetHeaderSize() + (kPointerSize * (index + map()->has_external_resource()?1:0))); - } - - -@@ -1416,12 +1416,29 @@ void JSObject::SetInternalField(int index, Object* value) { - // Internal objects do follow immediately after the header, whereas in-object - // properties are at the end of the object. Therefore there is no need - // to adjust the index here. -- int offset = GetHeaderSize() + (kPointerSize * index); -+ int offset = GetHeaderSize() + (kPointerSize * (index + map()->has_external_resource()?1:0)); - WRITE_FIELD(this, offset, value); - WRITE_BARRIER(this, offset); - } - - -+void JSObject::SetExternalResourceObject(Object *value) { -+ ASSERT(map()->has_external_resource()); -+ int offset = GetHeaderSize(); -+ WRITE_FIELD(this, offset, value); -+ WRITE_BARRIER(this, offset); -+} -+ -+ -+Object *JSObject::GetExternalResourceObject() { -+ if (map()->has_external_resource()) { -+ return READ_FIELD(this, GetHeaderSize()); -+ } 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. -@@ -2521,6 +2538,20 @@ bool Map::is_shared() { - } - - -+void Map::set_has_external_resource(bool value) { -+ if (value) { -+ set_bit_field3(bit_field3() | (1 << kHasExternalResource)); -+ } else { -+ set_bit_field3(bit_field3() & ~(1 << kHasExternalResource)); -+ } -+} -+ -+bool Map::has_external_resource() -+{ -+ return ((1 << kHasExternalResource) & bit_field3()) != 0; -+} -+ -+ - void Map::set_named_interceptor_is_fallback(bool value) - { - if (value) { -@@ -3017,6 +3048,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 a209cd0..1bdb5c7 100644 ---- a/src/objects.h -+++ b/src/objects.h -@@ -1636,6 +1636,9 @@ class JSObject: public HeapObject { - inline Object* GetInternalField(int index); - inline void SetInternalField(int index, Object* value); - -+ inline void SetExternalResourceObject(Object *); -+ inline Object *GetExternalResourceObject(); -+ - // Lookup a property. If found, the result is valid and has - // detailed information. - void LocalLookup(String* name, LookupResult* result, bool skip_fallback_interceptor = false); -@@ -3715,6 +3718,12 @@ class Map: public HeapObject { - inline void set_is_access_check_needed(bool access_check_needed); - inline bool is_access_check_needed(); - -+ -+ // 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(); -+ - - // Whether the named interceptor is a fallback interceptor or not - inline void set_named_interceptor_is_fallback(bool value); -@@ -3912,6 +3921,7 @@ class Map: public HeapObject { - - // Bit positions for bit field 3 - static const int kNamedInterceptorIsFallback = 0; -+ static const int kHasExternalResource = 1; - - // Layout of the default cache. It holds alternating name and code objects. - static const int kCodeCacheEntrySize = 2; -@@ -6426,6 +6436,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); - -@@ -6442,7 +6453,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.4 - diff --git a/src/v8/0005-Introduce-a-QML-compilation-mode.patch b/src/v8/0004-Introduce-a-QML-compilation-mode.patch index c5c36a1f95..4b79d94e68 100644 --- a/src/v8/0005-Introduce-a-QML-compilation-mode.patch +++ b/src/v8/0004-Introduce-a-QML-compilation-mode.patch @@ -1,7 +1,7 @@ -From 60c1a26bf89d3b06bcdd8408fcee89a018120f32 Mon Sep 17 00:00:00 2001 +From 27ef7b7b37255a9965fe31fb7597720f57ed5154 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 05/16] Introduce a QML compilation mode +Date: Wed, 5 Oct 2011 13:01:30 +1000 +Subject: [PATCH 04/11] 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,10 +15,10 @@ 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 ++++++++++++++++++++++----- + include/v8.h | 19 ++++++++-- + src/api.cc | 52 ++++++++++++++++++++++++----- src/arm/code-stubs-arm.cc | 4 ++ - src/arm/full-codegen-arm.cc | 26 ++++++++------ + src/arm/full-codegen-arm.cc | 28 +++++++++------- src/arm/lithium-arm.cc | 2 +- src/arm/lithium-arm.h | 6 +++- src/arm/lithium-codegen-arm.cc | 7 ++-- @@ -27,46 +27,46 @@ runs. src/ast.h | 1 + src/code-stubs.h | 2 +- src/compiler.cc | 15 +++++++- - src/compiler.h | 22 +++++++++-- - src/contexts.cc | 35 ++++++++++++++++++ + src/compiler.h | 16 +++++++-- + src/contexts.cc | 35 +++++++++++++++++++ src/contexts.h | 4 ++ - src/execution.cc | 28 ++++++++++++-- - src/execution.h | 6 +++ + src/execution.cc | 31 ++++++++++++++--- + src/execution.h | 8 ++++ src/full-codegen.cc | 3 +- src/full-codegen.h | 1 + - src/heap.cc | 2 + - src/hydrogen-instructions.h | 10 ++++- + src/heap.cc | 4 ++ + src/hydrogen-instructions.h | 8 ++++- src/hydrogen.cc | 2 + - src/ia32/code-stubs-ia32.cc | 7 ++++ - src/ia32/full-codegen-ia32.cc | 26 ++++++++------ + src/ia32/code-stubs-ia32.cc | 5 +++ + src/ia32/full-codegen-ia32.cc | 28 +++++++++------- 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/ia32/macro-assembler-ia32.h | 3 ++ + src/objects-inl.h | 2 + + src/objects.h | 4 ++ + src/parser.cc | 27 +++++++++++++-- src/parser.h | 4 ++- src/prettyprinter.cc | 3 ++ - src/runtime.cc | 72 ++++++++++++++++++++++++------------- + src/runtime.cc | 68 +++++++++++++++++++++++++------------- src/runtime.h | 8 ++-- - src/scopes.cc | 59 +++++++++++++++++++++++++++++++ - src/scopes.h | 7 ++++ + src/scopes.cc | 61 ++++++++++++++++++++++++++++++++++ + src/scopes.h | 8 ++++ src/variables.cc | 3 +- src/variables.h | 5 +++ src/x64/code-stubs-x64.cc | 4 ++ - src/x64/full-codegen-x64.cc | 26 ++++++++------ + src/x64/full-codegen-x64.cc | 28 +++++++++------- 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, 455 insertions(+), 109 deletions(-) + 45 files changed, 445 insertions(+), 109 deletions(-) diff --git a/include/v8.h b/include/v8.h -index 205e856..d78ab1f 100644 +index 3ef4dd6..193e2fe 100644 --- a/include/v8.h +++ b/include/v8.h -@@ -577,6 +577,10 @@ class ScriptOrigin { +@@ -587,6 +587,11 @@ class ScriptOrigin { */ class V8EXPORT Script { public: @@ -74,10 +74,11 @@ index 205e856..d78ab1f 100644 + Default = 0x00, + QmlMode = 0x01 + }; - ++ /** * Compiles the specified script (context-independent). -@@ -596,7 +600,8 @@ class V8EXPORT Script { + * +@@ -605,7 +610,8 @@ class V8EXPORT Script { static Local<Script> New(Handle<String> source, ScriptOrigin* origin = NULL, ScriptData* pre_data = NULL, @@ -87,7 +88,7 @@ index 205e856..d78ab1f 100644 /** * Compiles the specified script using the specified file name -@@ -609,7 +614,8 @@ class V8EXPORT Script { +@@ -618,7 +624,8 @@ class V8EXPORT Script { * will use the currently entered context). */ static Local<Script> New(Handle<String> source, @@ -97,7 +98,7 @@ index 205e856..d78ab1f 100644 /** * Compiles the specified script (bound to current context). -@@ -630,7 +636,8 @@ class V8EXPORT Script { +@@ -639,7 +646,8 @@ class V8EXPORT Script { static Local<Script> Compile(Handle<String> source, ScriptOrigin* origin = NULL, ScriptData* pre_data = NULL, @@ -107,7 +108,7 @@ index 205e856..d78ab1f 100644 /** * Compiles the specified script using the specified file name -@@ -647,7 +654,8 @@ class V8EXPORT Script { +@@ -656,7 +664,8 @@ class V8EXPORT Script { */ static Local<Script> Compile(Handle<String> source, Handle<Value> file_name, @@ -117,7 +118,7 @@ index 205e856..d78ab1f 100644 /** * Runs the script returning the resulting value. If the script is -@@ -657,6 +665,7 @@ class V8EXPORT Script { +@@ -666,6 +675,7 @@ class V8EXPORT Script { * compiled. */ Local<Value> Run(); @@ -125,7 +126,7 @@ index 205e856..d78ab1f 100644 /** * Returns the script id value. -@@ -3327,6 +3336,7 @@ class V8EXPORT Context { +@@ -3506,6 +3516,7 @@ class V8EXPORT Context { * JavaScript frames an empty handle is returned. */ static Local<Context> GetCalling(); @@ -134,10 +135,10 @@ index 205e856..d78ab1f 100644 /** * Sets the security token for the context. To access an object in diff --git a/src/api.cc b/src/api.cc -index 1a6fbbb..39767f4 100644 +index 85f0d4b..fd718c8 100644 --- a/src/api.cc +++ b/src/api.cc -@@ -1372,7 +1372,8 @@ ScriptData* ScriptData::New(const char* data, int length) { +@@ -1514,7 +1514,8 @@ ScriptData* ScriptData::New(const char* data, int length) { Local<Script> Script::New(v8::Handle<String> source, v8::ScriptOrigin* origin, v8::ScriptData* pre_data, @@ -147,7 +148,7 @@ index 1a6fbbb..39767f4 100644 i::Isolate* isolate = i::Isolate::Current(); ON_BAILOUT(isolate, "v8::Script::New()", return Local<Script>()); LOG_API(isolate, "Script::New"); -@@ -1409,7 +1410,8 @@ Local<Script> Script::New(v8::Handle<String> source, +@@ -1551,7 +1552,8 @@ Local<Script> Script::New(v8::Handle<String> source, NULL, pre_data_impl, Utils::OpenHandle(*script_data), @@ -157,12 +158,12 @@ index 1a6fbbb..39767f4 100644 has_pending_exception = result.is_null(); EXCEPTION_BAILOUT_CHECK(isolate, Local<Script>()); return Local<Script>(ToApi<Script>(result)); -@@ -1417,21 +1419,23 @@ Local<Script> Script::New(v8::Handle<String> source, +@@ -1559,21 +1561,23 @@ Local<Script> Script::New(v8::Handle<String> source, Local<Script> Script::New(v8::Handle<String> source, - v8::Handle<Value> file_name) { -+ v8::Handle<Value> file_name, ++ v8::Handle<Value> file_name, + v8::Script::CompileFlags compile_flags) { ScriptOrigin origin(file_name); - return New(source, &origin); @@ -185,7 +186,7 @@ index 1a6fbbb..39767f4 100644 if (generic.IsEmpty()) return generic; i::Handle<i::Object> obj = Utils::OpenHandle(*generic); -@@ -1447,13 +1451,18 @@ Local<Script> Script::Compile(v8::Handle<String> source, +@@ -1589,13 +1593,18 @@ Local<Script> Script::Compile(v8::Handle<String> source, Local<Script> Script::Compile(v8::Handle<String> source, v8::Handle<Value> file_name, @@ -206,7 +207,7 @@ index 1a6fbbb..39767f4 100644 i::Isolate* isolate = i::Isolate::Current(); ON_BAILOUT(isolate, "v8::Script::Run()", return Local<Value>()); LOG_API(isolate, "Script::Run"); -@@ -1472,10 +1481,11 @@ Local<Value> Script::Run() { +@@ -1614,10 +1623,11 @@ Local<Value> Script::Run() { fun = i::Handle<i::JSFunction>(i::JSFunction::cast(*obj), isolate); } EXCEPTION_PREAMBLE(isolate); @@ -215,11 +216,11 @@ index 1a6fbbb..39767f4 100644 isolate->context()->global_proxy(), isolate); i::Handle<i::Object> result = - i::Execution::Call(fun, receiver, 0, NULL, &has_pending_exception); -+ i::Execution::Call(fun, receiver, 0, NULL, &has_pending_exception, qmlglobal); ++ i::Execution::Call(fun, receiver, 0, NULL, &has_pending_exception, false, qmlglobal); EXCEPTION_BAILOUT_CHECK(isolate, Local<Value>()); raw_result = *result; } -@@ -3943,6 +3953,30 @@ v8::Local<v8::Context> Context::GetCalling() { +@@ -4328,6 +4338,30 @@ v8::Local<v8::Context> Context::GetCalling() { } @@ -251,10 +252,10 @@ index 1a6fbbb..39767f4 100644 if (IsDeadCheck(i::Isolate::Current(), "v8::Context::Global()")) { return Local<v8::Object>(); diff --git a/src/arm/code-stubs-arm.cc b/src/arm/code-stubs-arm.cc -index 8c147f9..a2626bf 100644 +index 17dfbd7..00ac676 100644 --- a/src/arm/code-stubs-arm.cc +++ b/src/arm/code-stubs-arm.cc -@@ -166,6 +166,10 @@ void FastNewContextStub::Generate(MacroAssembler* masm) { +@@ -172,6 +172,10 @@ void FastNewContextStub::Generate(MacroAssembler* masm) { __ ldr(r1, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_INDEX))); __ str(r1, MemOperand(r0, Context::SlotOffset(Context::GLOBAL_INDEX))); @@ -266,13 +267,13 @@ 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..a69f10d 100644 +index 2ee1594..a1841f2 100644 --- a/src/arm/full-codegen-arm.cc +++ b/src/arm/full-codegen-arm.cc -@@ -154,12 +154,13 @@ void FullCodeGenerator::Generate(CompilationInfo* info) { +@@ -182,12 +182,13 @@ void FullCodeGenerator::Generate(CompilationInfo* info) { // Possibly allocate a local context. - int heap_slots = scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; + int heap_slots = info->scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; - if (heap_slots > 0) { + if (heap_slots > 0 || + (scope()->is_qml_mode() && scope()->is_global_scope())) { @@ -284,49 +285,44 @@ index 871b453..a69f10d 100644 + FastNewContextStub stub((heap_slots < 0)?0:heap_slots); __ CallStub(&stub); } else { - __ CallRuntime(Runtime::kNewContext, 1); -@@ -1247,9 +1248,9 @@ void FullCodeGenerator::EmitLoadGlobalSlotCheckExtensions( + __ CallRuntime(Runtime::kNewFunctionContext, 1); +@@ -1168,9 +1169,9 @@ void FullCodeGenerator::EmitLoadGlobalCheckExtensions(Variable* var, __ bind(&fast); } - __ ldr(r0, GlobalObjectOperand()); -+ __ ldr(r0, slot->var()->is_qml_global()?QmlGlobalObjectOperand():GlobalObjectOperand()); - __ mov(r2, Operand(slot->var()->name())); ++ __ ldr(r0, var->is_qml_global()?QmlGlobalObjectOperand():GlobalObjectOperand()); + __ mov(r2, Operand(var->name())); - RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF) -+ RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF || slot->var()->is_qml_global()) ++ RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF || var->is_qml_global()) ? RelocInfo::CODE_TARGET : RelocInfo::CODE_TARGET_CONTEXT; Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); -@@ -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. -- __ ldr(r0, GlobalObjectOperand()); -+ __ ldr(r0, var->is_qml_global()?QmlGlobalObjectOperand():GlobalObjectOperand()); - __ mov(r2, Operand(var->name())); - Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); -- EmitCallIC(ic, RelocInfo::CODE_TARGET_CONTEXT); -+ EmitCallIC(ic, var->is_qml_global()?RelocInfo::CODE_TARGET:RelocInfo::CODE_TARGET_CONTEXT); - context()->Plug(r0); - - } else if (slot != NULL && slot->type() == Slot::LOOKUP) { -@@ -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. +@@ -1246,10 +1247,10 @@ void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) { + Comment cmnt(masm_, "Global variable"); + // Use inline caching. Variable name is passed in r2 and the global + // object (receiver) in r0. +- __ ldr(r0, GlobalObjectOperand()); ++ __ ldr(r0, var->is_qml_global()?QmlGlobalObjectOperand():GlobalObjectOperand()); + __ mov(r2, Operand(var->name())); + Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); +- __ Call(ic, RelocInfo::CODE_TARGET_CONTEXT); ++ __ Call(ic, var->is_qml_global()?RelocInfo::CODE_TARGET:RelocInfo::CODE_TARGET_CONTEXT); + context()->Plug(r0); + break; + } +@@ -1840,7 +1841,7 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var, + if (var->IsUnallocated()) { + // Global var, const, or let. __ mov(r2, Operand(var->name())); - __ ldr(r1, GlobalObjectOperand()); + __ ldr(r1, var->is_qml_global()?QmlGlobalObjectOperand():GlobalObjectOperand()); Handle<Code> ic = is_strict_mode() ? isolate()->builtins()->StoreIC_Initialize_Strict() : isolate()->builtins()->StoreIC_Initialize(); -- EmitCallIC(ic, RelocInfo::CODE_TARGET_CONTEXT); -+ EmitCallIC(ic, var->is_qml_global()?RelocInfo::CODE_TARGET:RelocInfo::CODE_TARGET_CONTEXT); - - } else if (op == Token::INIT_CONST) { - // Like var declarations, const declarations are hoisted to function -@@ -2184,10 +2185,13 @@ void FullCodeGenerator::EmitResolvePossiblyDirectEval(ResolveEvalFlag flag, - // Push the strict mode flag. - __ mov(r1, Operand(Smi::FromInt(strict_mode_flag()))); +@@ -2141,10 +2142,13 @@ void FullCodeGenerator::EmitResolvePossiblyDirectEval(ResolveEvalFlag flag, + } + __ mov(r1, Operand(Smi::FromInt(strict_mode))); __ push(r1); + // Push the qml mode flag. + __ mov(r1, Operand(Smi::FromInt(is_qml_mode()))); @@ -339,23 +335,41 @@ index 871b453..a69f10d 100644 } -@@ -2263,9 +2267,9 @@ void FullCodeGenerator::VisitCall(Call* expr) { +@@ -2217,9 +2221,9 @@ void FullCodeGenerator::VisitCall(Call* expr) { context()->DropAndPlug(1, r0); - } else if (var != NULL && !var->is_this() && var->is_global()) { + } else if (proxy != NULL && proxy->var()->IsUnallocated()) { // Push global object as receiver for the call IC. - __ ldr(r0, GlobalObjectOperand()); -+ __ ldr(r0, var->is_qml_global()?QmlGlobalObjectOperand():GlobalObjectOperand()); ++ __ ldr(r0, proxy->var()->is_qml_global()?QmlGlobalObjectOperand():GlobalObjectOperand()); __ push(r0); -- EmitCallWithIC(expr, var->name(), RelocInfo::CODE_TARGET_CONTEXT); -+ EmitCallWithIC(expr, var->name(), var->is_qml_global()?RelocInfo::CODE_TARGET:RelocInfo::CODE_TARGET_CONTEXT); - } else if (var != NULL && var->AsSlot() != NULL && - var->AsSlot()->type() == Slot::LOOKUP) { +- EmitCallWithIC(expr, proxy->name(), RelocInfo::CODE_TARGET_CONTEXT); ++ EmitCallWithIC(expr, proxy->name(), proxy->var()->is_qml_global()?RelocInfo::CODE_TARGET:RelocInfo::CODE_TARGET_CONTEXT); + } else if (proxy != NULL && proxy->var()->IsLookupSlot()) { // Call to a lookup slot (dynamically introduced variable). + Label slow, done; +@@ -3630,7 +3634,7 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { + // but "delete this" is allowed. + ASSERT(strict_mode_flag() == kNonStrictMode || var->is_this()); + if (var->IsUnallocated()) { +- __ ldr(r2, GlobalObjectOperand()); ++ __ ldr(r2, var->is_qml_global() ? QmlGlobalObjectOperand() : GlobalObjectOperand()); + __ mov(r1, Operand(var->name())); + __ mov(r0, Operand(Smi::FromInt(kNonStrictMode))); + __ Push(r2, r1, r0); +@@ -3916,7 +3920,7 @@ void FullCodeGenerator::VisitForTypeofValue(Expression* expr) { + VariableProxy* proxy = expr->AsVariableProxy(); + if (proxy != NULL && proxy->var()->IsUnallocated()) { + Comment cmnt(masm_, "Global variable"); +- __ ldr(r0, GlobalObjectOperand()); ++ __ ldr(r0, proxy->var()->is_qml_global() ? QmlGlobalObjectOperand() : GlobalObjectOperand()); + __ mov(r2, Operand(proxy->name())); + Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); + // Use a regular load, not a contextual load, to avoid a reference diff --git a/src/arm/lithium-arm.cc b/src/arm/lithium-arm.cc -index 3f1d15b..8406a96 100644 +index 8495939..00582ea 100644 --- a/src/arm/lithium-arm.cc +++ b/src/arm/lithium-arm.cc -@@ -1195,7 +1195,7 @@ LInstruction* LChunkBuilder::DoOuterContext(HOuterContext* instr) { +@@ -1122,7 +1122,7 @@ LInstruction* LChunkBuilder::DoOuterContext(HOuterContext* instr) { LInstruction* LChunkBuilder::DoGlobalObject(HGlobalObject* instr) { LOperand* context = UseRegisterAtStart(instr->value()); @@ -365,10 +379,10 @@ index 3f1d15b..8406a96 100644 diff --git a/src/arm/lithium-arm.h b/src/arm/lithium-arm.h -index 6da7c86..10b901f 100644 +index 73c7e45..49cdccc 100644 --- a/src/arm/lithium-arm.h +++ b/src/arm/lithium-arm.h -@@ -1378,13 +1378,17 @@ class LOuterContext: public LTemplateInstruction<1, 1, 0> { +@@ -1301,13 +1301,17 @@ class LOuterContext: public LTemplateInstruction<1, 1, 0> { class LGlobalObject: public LTemplateInstruction<1, 1, 0> { public: @@ -388,10 +402,10 @@ index 6da7c86..10b901f 100644 diff --git a/src/arm/lithium-codegen-arm.cc b/src/arm/lithium-codegen-arm.cc -index 4912449..db114ea 100644 +index f6750a2..63c8463 100644 --- a/src/arm/lithium-codegen-arm.cc +++ b/src/arm/lithium-codegen-arm.cc -@@ -166,12 +166,13 @@ bool LCodeGen::GeneratePrologue() { +@@ -190,12 +190,13 @@ bool LCodeGen::GeneratePrologue() { // Possibly allocate a local context. int heap_slots = scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; @@ -406,10 +420,10 @@ index 4912449..db114ea 100644 + FastNewContextStub stub((heap_slots < 0)?0:heap_slots); __ CallStub(&stub); } else { - __ CallRuntime(Runtime::kNewContext, 1); -@@ -2664,7 +2665,7 @@ void LCodeGen::DoOuterContext(LOuterContext* instr) { + __ CallRuntime(Runtime::kNewFunctionContext, 1); +@@ -2798,7 +2799,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)); @@ -417,10 +431,10 @@ index 4912449..db114ea 100644 diff --git a/src/arm/macro-assembler-arm.h b/src/arm/macro-assembler-arm.h -index ab5efb0..d40cdbc 100644 +index d42ccec..9adeb36 100644 --- a/src/arm/macro-assembler-arm.h +++ b/src/arm/macro-assembler-arm.h -@@ -1056,6 +1056,11 @@ static inline MemOperand GlobalObjectOperand() { +@@ -1260,6 +1260,11 @@ static inline MemOperand GlobalObjectOperand() { } @@ -433,10 +447,10 @@ index ab5efb0..d40cdbc 100644 #define CODE_COVERAGE_STRINGIFY(x) #x #define CODE_COVERAGE_TOSTRING(x) CODE_COVERAGE_STRINGIFY(x) diff --git a/src/ast-inl.h b/src/ast-inl.h -index d80684a..adc5a1f 100644 +index 731ad2f..15702cf 100644 --- a/src/ast-inl.h +++ b/src/ast-inl.h -@@ -106,6 +106,11 @@ bool FunctionLiteral::strict_mode() const { +@@ -116,6 +116,11 @@ bool FunctionLiteral::strict_mode() const { } @@ -449,22 +463,22 @@ index d80684a..adc5a1f 100644 #endif // V8_AST_INL_H_ diff --git a/src/ast.h b/src/ast.h -index 65a25a9..f790dc0 100644 +index 00cfd7f..319d090 100644 --- a/src/ast.h +++ b/src/ast.h -@@ -1712,6 +1712,7 @@ class FunctionLiteral: public Expression { - int end_position() const { return end_position_; } +@@ -1658,6 +1658,7 @@ class FunctionLiteral: public Expression { bool is_expression() const { return is_expression_; } + bool is_anonymous() const { return is_anonymous_; } bool strict_mode() const; + bool qml_mode() const; 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 +index 9d4baf4..b7cac89 100644 --- a/src/code-stubs.h +++ b/src/code-stubs.h -@@ -303,7 +303,7 @@ class FastNewContextStub : public CodeStub { +@@ -323,7 +323,7 @@ class FastNewContextStub : public CodeStub { static const int kMaximumSlots = 64; explicit FastNewContextStub(int slots) : slots_(slots) { @@ -474,10 +488,10 @@ index 56ef072..37e5383 100644 void Generate(MacroAssembler* masm); diff --git a/src/compiler.cc b/src/compiler.cc -index 86d5de3..d2191b9 100755 +index 5a86b4e..596df4a 100644 --- a/src/compiler.cc +++ b/src/compiler.cc -@@ -462,7 +462,8 @@ Handle<SharedFunctionInfo> Compiler::Compile(Handle<String> source, +@@ -450,7 +450,8 @@ Handle<SharedFunctionInfo> Compiler::Compile(Handle<String> source, v8::Extension* extension, ScriptDataImpl* input_pre_data, Handle<Object> script_data, @@ -487,15 +501,15 @@ index 86d5de3..d2191b9 100755 Isolate* isolate = source->GetIsolate(); int source_length = source->length(); isolate->counters()->total_load_size()->Increment(source_length); -@@ -523,6 +524,7 @@ Handle<SharedFunctionInfo> Compiler::Compile(Handle<String> source, +@@ -517,6 +518,7 @@ Handle<SharedFunctionInfo> Compiler::Compile(Handle<String> source, info.MarkAsGlobal(); info.SetExtension(extension); info.SetPreParseData(pre_data); + if (compile_flags & v8::Script::QmlMode) info.MarkAsQmlMode(); - if (natives == NATIVES_CODE) info.MarkAsAllowingNativesSyntax(); - result = MakeFunctionInfo(&info); - if (extension == NULL && !result.is_null()) { -@@ -543,7 +545,8 @@ Handle<SharedFunctionInfo> Compiler::Compile(Handle<String> source, + if (natives == NATIVES_CODE) { + info.MarkAsAllowingNativesSyntax(); + } +@@ -539,7 +541,8 @@ Handle<SharedFunctionInfo> Compiler::Compile(Handle<String> source, Handle<SharedFunctionInfo> Compiler::CompileEval(Handle<String> source, Handle<Context> context, bool is_global, @@ -505,7 +519,7 @@ index 86d5de3..d2191b9 100755 Isolate* isolate = source->GetIsolate(); int source_length = source->length(); isolate->counters()->total_eval_size()->Increment(source_length); -@@ -567,6 +570,7 @@ Handle<SharedFunctionInfo> Compiler::CompileEval(Handle<String> source, +@@ -563,6 +566,7 @@ Handle<SharedFunctionInfo> Compiler::CompileEval(Handle<String> source, CompilationInfo info(script); info.MarkAsEval(); if (is_global) info.MarkAsGlobal(); @@ -513,7 +527,7 @@ index 86d5de3..d2191b9 100755 if (strict_mode == kStrictMode) info.MarkAsStrictMode(); info.SetCallingContext(context); result = MakeFunctionInfo(&info); -@@ -610,6 +614,12 @@ bool Compiler::CompileLazy(CompilationInfo* info) { +@@ -607,6 +611,12 @@ bool Compiler::CompileLazy(CompilationInfo* info) { info->MarkAsStrictMode(); } @@ -526,23 +540,23 @@ index 86d5de3..d2191b9 100755 // Compile the code. if (!MakeCode(info)) { if (!isolate->has_pending_exception()) { -@@ -755,6 +765,7 @@ void Compiler::SetFunctionInfo(Handle<SharedFunctionInfo> function_info, +@@ -752,6 +762,7 @@ void Compiler::SetFunctionInfo(Handle<SharedFunctionInfo> function_info, *lit->this_property_assignments()); function_info->set_allows_lazy_compilation(lit->AllowsLazyCompilation()); function_info->set_strict_mode(lit->strict_mode()); + function_info->set_qml_mode(lit->qml_mode()); + function_info->set_uses_arguments(lit->scope()->arguments() != NULL); + function_info->set_has_duplicate_parameters(lit->has_duplicate_parameters()); } - - diff --git a/src/compiler.h b/src/compiler.h -index e75e869..17cd369 100644 +index 09aa23d..8eacb71 100644 --- a/src/compiler.h +++ b/src/compiler.h @@ -54,6 +54,7 @@ class CompilationInfo BASE_EMBEDDED { - bool is_global() const { return (flags_ & IsGlobal::mask()) != 0; } - bool is_strict_mode() const { return (flags_ & IsStrictMode::mask()) != 0; } - bool is_in_loop() const { return (flags_ & IsInLoop::mask()) != 0; } -+ bool is_qml_mode() const { return (flags_ & IsQmlMode::mask()) != 0; } + bool is_global() const { return IsGlobal::decode(flags_); } + bool is_strict_mode() const { return IsStrictMode::decode(flags_); } + bool is_in_loop() const { return IsInLoop::decode(flags_); } ++ bool is_qml_mode() const { return IsQmlMode::decode(flags_); } FunctionLiteral* function() const { return function_; } Scope* scope() const { return scope_; } Handle<Code> code() const { return code_; } @@ -556,46 +570,33 @@ index e75e869..17cd369 100644 void MarkAsAllowingNativesSyntax() { flags_ |= IsNativesSyntaxAllowed::encode(true); } -@@ -141,6 +145,7 @@ class CompilationInfo BASE_EMBEDDED { - - // Determine whether or not we can adaptively optimize. - bool AllowOptimize() { -+ // XXX - fix qml mode optimizations - return V8::UseCrankshaft() && !closure_.is_null(); - } - -@@ -163,8 +168,13 @@ class CompilationInfo BASE_EMBEDDED { - - void Initialize(Mode mode) { - mode_ = V8::UseCrankshaft() ? mode : NONOPT; -- if (!shared_info_.is_null() && shared_info_->strict_mode()) { -- MarkAsStrictMode(); -+ if (!shared_info_.is_null()) { -+ if (shared_info_->strict_mode()) { -+ MarkAsStrictMode(); -+ } -+ if (shared_info_->qml_mode()) { -+ MarkAsQmlMode(); -+ } +@@ -180,6 +184,9 @@ class CompilationInfo BASE_EMBEDDED { + if (!shared_info_.is_null() && shared_info_->strict_mode()) { + MarkAsStrictMode(); } ++ if (!shared_info_.is_null() && shared_info_->qml_mode()) { ++ MarkAsQmlMode(); ++ } } -@@ -187,6 +197,8 @@ class CompilationInfo BASE_EMBEDDED { - class IsStrictMode: public BitField<bool, 4, 1> {}; - // Native syntax (%-stuff) allowed? + void SetMode(Mode mode) { +@@ -203,7 +210,8 @@ class CompilationInfo BASE_EMBEDDED { class IsNativesSyntaxAllowed: public BitField<bool, 5, 1> {}; + // Is this a function from our natives. + class IsNative: public BitField<bool, 6, 1> {}; +- + // Qml mode -+ class IsQmlMode: public BitField<bool, 6, 1> {}; ++ class IsQmlMode: public BitField<bool, 7, 1> {}; unsigned flags_; -@@ -252,13 +264,15 @@ class Compiler : public AllStatic { +@@ -269,13 +277,15 @@ class Compiler : public AllStatic { v8::Extension* extension, ScriptDataImpl* pre_data, Handle<Object> script_data, - NativesFlag is_natives_code); + NativesFlag is_natives_code, -+ v8::Script::CompileFlags compile_flags = v8::Script::Default); ++ v8::Script::CompileFlags = v8::Script::Default); // Compile a String source within a context for Eval. static Handle<SharedFunctionInfo> CompileEval(Handle<String> source, @@ -608,10 +609,10 @@ index e75e869..17cd369 100644 // Compile from function info (used for lazy compilation). Returns true on // success and false if the compilation resulted in a stack overflow. diff --git a/src/contexts.cc b/src/contexts.cc -index 520f3dd..035ac3b 100644 +index 007d30d..825493a 100644 --- a/src/contexts.cc +++ b/src/contexts.cc -@@ -89,6 +89,9 @@ Handle<Object> Context::Lookup(Handle<String> name, ContextLookupFlags flags, +@@ -103,6 +103,9 @@ Handle<Object> Context::Lookup(Handle<String> name, PrintF(")\n"); } @@ -621,8 +622,8 @@ index 520f3dd..035ac3b 100644 do { if (FLAG_trace_contexts) { PrintF(" - looking in context %p", reinterpret_cast<void*>(*context)); -@@ -119,6 +122,11 @@ Handle<Object> Context::Lookup(Handle<String> name, ContextLookupFlags flags, - } +@@ -110,6 +113,11 @@ Handle<Object> Context::Lookup(Handle<String> name, + PrintF("\n"); } + if (qml_global.is_null() && !context->qml_global()->IsUndefined()) { @@ -630,10 +631,10 @@ index 520f3dd..035ac3b 100644 + qml_global_global = Handle<JSObject>(context->global(), isolate); + } + - if (context->is_function_context()) { - // we have context-local slots - -@@ -198,6 +206,33 @@ Handle<Object> Context::Lookup(Handle<String> name, ContextLookupFlags flags, + // 1. Check global objects, subjects of with, and extension objects. + if (context->IsGlobalContext() || + context->IsWithContext() || +@@ -221,6 +229,33 @@ Handle<Object> Context::Lookup(Handle<String> name, } } while (follow_context_chain); @@ -664,22 +665,22 @@ index 520f3dd..035ac3b 100644 + } + } + - // slot not found if (FLAG_trace_contexts) { PrintF("=> no property/slot found\n"); + } diff --git a/src/contexts.h b/src/contexts.h -index e46619e..57d8e7b 100644 +index b80475f..28ba69e 100644 --- a/src/contexts.h +++ b/src/contexts.h -@@ -182,6 +182,7 @@ class Context: public FixedArray { - FCONTEXT_INDEX, - PREVIOUS_INDEX, +@@ -196,6 +196,7 @@ class Context: public FixedArray { + // contexts), eval extension object (function contexts), subject of with + // (with contexts), or the variable name (catch contexts). EXTENSION_INDEX, + QML_GLOBAL_INDEX, GLOBAL_INDEX, MIN_CONTEXT_SLOTS, -@@ -273,6 +274,9 @@ class Context: public FixedArray { +@@ -297,6 +298,9 @@ class Context: public FixedArray { } void set_global(GlobalObject* global) { set(GLOBAL_INDEX, global); } @@ -690,10 +691,10 @@ index e46619e..57d8e7b 100644 JSObject* global_proxy(); void set_global_proxy(JSObject* global); diff --git a/src/execution.cc b/src/execution.cc -index eb26438..1632076 100644 +index 2021c0f..c64c9ea 100644 --- a/src/execution.cc +++ b/src/execution.cc -@@ -70,7 +70,8 @@ static Handle<Object> Invoke(bool construct, +@@ -71,7 +71,8 @@ static Handle<Object> Invoke(bool construct, Handle<Object> receiver, int argc, Object*** args, @@ -703,7 +704,7 @@ index eb26438..1632076 100644 Isolate* isolate = func->GetIsolate(); // Entering JavaScript. -@@ -107,6 +108,12 @@ static Handle<Object> Invoke(bool construct, +@@ -106,6 +107,12 @@ static Handle<Object> Invoke(bool construct, // make the current one is indeed a global object. ASSERT(func->context()->global()->IsGlobalObject()); @@ -716,7 +717,7 @@ index eb26438..1632076 100644 { // Save and restore context around invocation and block the // allocation of handles without explicit handle scopes. -@@ -122,6 +129,9 @@ static Handle<Object> Invoke(bool construct, +@@ -121,6 +128,9 @@ static Handle<Object> Invoke(bool construct, receiver_pointer, argc, args); } @@ -726,21 +727,31 @@ index eb26438..1632076 100644 #ifdef DEBUG value->Verify(); #endif -@@ -150,14 +160,24 @@ Handle<Object> Execution::Call(Handle<JSFunction> func, +@@ -149,7 +159,18 @@ Handle<Object> Execution::Call(Handle<Object> callable, int argc, Object*** args, - bool* pending_exception) { -- return Invoke(false, func, receiver, argc, args, pending_exception); -+ return Invoke(false, func, receiver, argc, args, pending_exception, Handle<Object>()); + bool* pending_exception, +- bool convert_receiver) { ++ bool convert_receiver) ++{ ++ return Call(callable, receiver, argc, args, pending_exception, convert_receiver, Handle<Object>()); +} + -+ -+Handle<Object> Execution::Call(Handle<JSFunction> func, ++Handle<Object> Execution::Call(Handle<Object> callable, + Handle<Object> receiver, + int argc, + Object*** args, + bool* pending_exception, ++ bool convert_receiver, + Handle<Object> qml) { + *pending_exception = false; + + if (!callable->IsJSFunction()) { +@@ -173,14 +194,14 @@ Handle<Object> Execution::Call(Handle<Object> callable, + if (*pending_exception) return callable; + } + +- return Invoke(false, func, receiver, argc, args, pending_exception); + return Invoke(false, func, receiver, argc, args, pending_exception, qml); } @@ -753,8 +764,8 @@ index eb26438..1632076 100644 } -@@ -175,7 +195,7 @@ Handle<Object> Execution::TryCall(Handle<JSFunction> func, - catcher.SetCaptureMessage(false); +@@ -199,7 +220,7 @@ Handle<Object> Execution::TryCall(Handle<JSFunction> func, + *caught_exception = false; Handle<Object> result = Invoke(false, func, receiver, argc, args, - caught_exception); @@ -763,36 +774,38 @@ index eb26438..1632076 100644 if (*caught_exception) { ASSERT(catcher.HasCaught()); diff --git a/src/execution.h b/src/execution.h -index d4b80d2..a476eb4 100644 +index 9fa6e78..baa58b5 100644 --- a/src/execution.h +++ b/src/execution.h -@@ -56,6 +56,12 @@ class Execution : public AllStatic { - int argc, - Object*** args, - bool* pending_exception); -+ static Handle<Object> Call(Handle<JSFunction> func, +@@ -65,6 +65,14 @@ class Execution : public AllStatic { + bool* pending_exception, + bool convert_receiver = false); + ++ static Handle<Object> Call(Handle<Object> callable, + Handle<Object> receiver, + int argc, + Object*** args, + bool* pending_exception, ++ bool convert_receiver, + Handle<Object> qml); - ++ // Construct object from function, the caller supplies an array of // arguments. Arguments are Object* type. After function returns, + // pointers in 'args' might be invalid. diff --git a/src/full-codegen.cc b/src/full-codegen.cc -index d6ba56e..2eaef0f 100644 +index e822588..516d237 100644 --- a/src/full-codegen.cc +++ b/src/full-codegen.cc -@@ -542,7 +542,7 @@ void FullCodeGenerator::VisitDeclarations( - // Do nothing in case of no declared global functions or variables. - if (globals > 0) { +@@ -512,7 +512,7 @@ void FullCodeGenerator::VisitDeclarations( + // Batch declare global functions and variables. + if (global_count > 0) { Handle<FixedArray> array = -- isolate()->factory()->NewFixedArray(2 * globals, TENURED); -+ isolate()->factory()->NewFixedArray(3 * globals, TENURED); +- isolate()->factory()->NewFixedArray(2 * global_count, TENURED); ++ isolate()->factory()->NewFixedArray(3 * global_count, TENURED); for (int j = 0, i = 0; i < length; i++) { Declaration* decl = declarations->at(i); Variable* var = decl->proxy()->var(); -@@ -567,6 +567,7 @@ void FullCodeGenerator::VisitDeclarations( +@@ -536,6 +536,7 @@ void FullCodeGenerator::VisitDeclarations( } array->set(j++, *function); } @@ -801,42 +814,58 @@ index d6ba56e..2eaef0f 100644 } // Invoke the platform-dependent code generator to do the actual diff --git a/src/full-codegen.h b/src/full-codegen.h -index d6ed1b9..e3241aa 100644 +index 6958dae..48753c5 100644 --- a/src/full-codegen.h +++ b/src/full-codegen.h -@@ -505,6 +505,7 @@ class FullCodeGenerator: public AstVisitor { +@@ -581,6 +581,7 @@ class FullCodeGenerator: public AstVisitor { StrictModeFlag strict_mode_flag() { return is_strict_mode() ? kStrictMode : kNonStrictMode; } + bool is_qml_mode() { return function()->qml_mode(); } FunctionLiteral* function() { return info_->function(); } - Scope* scope() { return info_->scope(); } + Scope* scope() { return scope_; } diff --git a/src/heap.cc b/src/heap.cc -index bf2940e..da958c2 100644 +index c730455..447dce1 100644 --- a/src/heap.cc +++ b/src/heap.cc -@@ -3795,6 +3795,7 @@ MaybeObject* Heap::AllocateFunctionContext(int length, JSFunction* function) { - context->set_previous(NULL); +@@ -4407,6 +4407,7 @@ MaybeObject* Heap::AllocateFunctionContext(int length, JSFunction* function) { + context->set_previous(function->context()); context->set_extension(NULL); context->set_global(function->context()->global()); + context->set_qml_global(function->context()->qml_global()); - ASSERT(!context->IsGlobalContext()); - ASSERT(context->is_function_context()); - ASSERT(result->IsContext()); -@@ -3817,6 +3818,7 @@ MaybeObject* Heap::AllocateWithContext(Context* previous, + return context; + } + +@@ -4427,6 +4428,7 @@ MaybeObject* Heap::AllocateCatchContext(JSFunction* function, + context->set_previous(previous); + context->set_extension(name); + context->set_global(previous->global()); ++ context->set_qml_global(previous->qml_global()); + context->set(Context::THROWN_OBJECT_INDEX, thrown_object); + return context; + } +@@ -4445,6 +4447,7 @@ MaybeObject* Heap::AllocateWithContext(JSFunction* function, context->set_previous(previous); context->set_extension(extension); context->set_global(previous->global()); + context->set_qml_global(previous->qml_global()); - ASSERT(!context->IsGlobalContext()); - ASSERT(!context->is_function_context()); - ASSERT(result->IsContext()); + return context; + } + +@@ -4463,6 +4466,7 @@ MaybeObject* Heap::AllocateBlockContext(JSFunction* function, + context->set_previous(previous); + context->set_extension(scope_info); + context->set_global(previous->global()); ++ context->set_qml_global(previous->qml_global()); + return context; + } + diff --git a/src/hydrogen-instructions.h b/src/hydrogen-instructions.h -index a623775..52455bc 100644 +index 6b43f53..d0e6fb0 100644 --- a/src/hydrogen-instructions.h +++ b/src/hydrogen-instructions.h -@@ -1148,7 +1148,7 @@ class HOuterContext: public HUnaryOperation { +@@ -1394,7 +1394,7 @@ class HOuterContext: public HUnaryOperation { class HGlobalObject: public HUnaryOperation { public: @@ -845,7 +874,7 @@ index a623775..52455bc 100644 set_representation(Representation::Tagged()); SetFlag(kUseGVN); } -@@ -1159,8 +1159,14 @@ class HGlobalObject: public HUnaryOperation { +@@ -1405,8 +1405,14 @@ class HGlobalObject: public HUnaryOperation { return Representation::Tagged(); } @@ -860,61 +889,50 @@ index a623775..52455bc 100644 }; -@@ -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 +index 64a6ae5..f0c1763 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); +@@ -3174,6 +3174,7 @@ void HGraphBuilder::VisitVariableProxy(VariableProxy* expr) { + } else { + HValue* context = environment()->LookupContext(); + 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, +@@ -3640,6 +3641,7 @@ void HGraphBuilder::HandleGlobalVariableAssignment(Variable* var, + } else { + HValue* context = environment()->LookupContext(); 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 +index 1ca577c..6cc80d3 100644 --- a/src/ia32/code-stubs-ia32.cc +++ b/src/ia32/code-stubs-ia32.cc -@@ -147,6 +147,13 @@ void FastNewContextStub::Generate(MacroAssembler* masm) { - __ mov(ebx, Operand(ebx, Context::SlotOffset(Context::GLOBAL_INDEX))); +@@ -143,6 +143,11 @@ void FastNewContextStub::Generate(MacroAssembler* masm) { + __ mov(ebx, Operand(esi, Context::SlotOffset(Context::GLOBAL_INDEX))); __ mov(Operand(eax, Context::SlotOffset(Context::GLOBAL_INDEX)), ebx); -+ // Copy the qml global object from the surrounding context. We go through the -+ // context in the function (ecx) to match the allocation behavior we have -+ // in the runtime system (see Heap::AllocateFunctionContext). -+ __ mov(ebx, FieldOperand(ecx, JSFunction::kContextOffset)); -+ __ mov(ebx, Operand(ebx, Context::SlotOffset(Context::QML_GLOBAL_INDEX))); ++ // Copy the qml global object from the previous context. ++ __ mov(ebx, Operand(esi, Context::SlotOffset(Context::QML_GLOBAL_INDEX))); + __ mov(Operand(eax, Context::SlotOffset(Context::QML_GLOBAL_INDEX)), ebx); + ++ // Initialize the rest of the slots to undefined. __ 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..0ddcde2 100644 +index d45a9cd..a5883a2 100644 --- a/src/ia32/full-codegen-ia32.cc +++ b/src/ia32/full-codegen-ia32.cc -@@ -142,12 +142,13 @@ void FullCodeGenerator::Generate(CompilationInfo* info) { +@@ -178,12 +178,13 @@ void FullCodeGenerator::Generate(CompilationInfo* info) { // Possibly allocate a local context. - int heap_slots = scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; + int heap_slots = info->scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; - if (heap_slots > 0) { + if (heap_slots > 0 || + (scope()->is_qml_mode() && scope()->is_global_scope())) { @@ -926,50 +944,45 @@ index 5d153a8..0ddcde2 100644 + FastNewContextStub stub((heap_slots < 0)?0:heap_slots); __ CallStub(&stub); } else { - __ CallRuntime(Runtime::kNewContext, 1); -@@ -1107,10 +1108,10 @@ void FullCodeGenerator::EmitLoadGlobalSlotCheckExtensions( + __ CallRuntime(Runtime::kNewFunctionContext, 1); +@@ -1152,10 +1153,10 @@ void FullCodeGenerator::EmitLoadGlobalCheckExtensions(Variable* var, // All extension objects were empty and it is safe to use a global // load IC call. - __ mov(eax, GlobalObjectOperand()); -+ __ mov(eax, slot->var()->is_qml_global()?QmlGlobalObjectOperand():GlobalObjectOperand()); - __ mov(ecx, slot->var()->name()); ++ __ mov(eax, var->is_qml_global()?QmlGlobalObjectOperand():GlobalObjectOperand()); + __ mov(ecx, var->name()); Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); - RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF) -+ RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF || slot->var()->is_qml_global()) ++ RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF || var->is_qml_global()) ? RelocInfo::CODE_TARGET : RelocInfo::CODE_TARGET_CONTEXT; - EmitCallIC(ic, mode); -@@ -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. -- __ mov(eax, GlobalObjectOperand()); -+ __ mov(eax, var->is_qml_global()?QmlGlobalObjectOperand():GlobalObjectOperand()); - __ mov(ecx, var->name()); - Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); -- EmitCallIC(ic, RelocInfo::CODE_TARGET_CONTEXT); -+ EmitCallIC(ic, var->is_qml_global()?RelocInfo::CODE_TARGET:RelocInfo::CODE_TARGET_CONTEXT); - context()->Plug(eax); - - } else if (slot != NULL && slot->type() == Slot::LOOKUP) { -@@ -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. + __ call(ic, mode); +@@ -1229,10 +1230,10 @@ void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) { + Comment cmnt(masm_, "Global variable"); + // Use inline caching. Variable name is passed in ecx and the global + // object in eax. +- __ mov(eax, GlobalObjectOperand()); ++ __ mov(eax, var->is_qml_global()?QmlGlobalObjectOperand():GlobalObjectOperand()); + __ mov(ecx, var->name()); + Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); +- __ call(ic, RelocInfo::CODE_TARGET_CONTEXT); ++ __ call(ic, var->is_qml_global()?RelocInfo::CODE_TARGET:RelocInfo::CODE_TARGET_CONTEXT); + context()->Plug(eax); + break; + } +@@ -1833,7 +1834,7 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var, + if (var->IsUnallocated()) { + // Global var, const, or let. __ mov(ecx, var->name()); - __ mov(edx, GlobalObjectOperand()); + __ mov(edx, var->is_qml_global()?QmlGlobalObjectOperand():GlobalObjectOperand()); Handle<Code> ic = is_strict_mode() ? isolate()->builtins()->StoreIC_Initialize_Strict() : isolate()->builtins()->StoreIC_Initialize(); -- EmitCallIC(ic, RelocInfo::CODE_TARGET_CONTEXT); -+ EmitCallIC(ic, var->is_qml_global()?RelocInfo::CODE_TARGET:RelocInfo::CODE_TARGET_CONTEXT); - - } else if (op == Token::INIT_CONST) { - // Like var declarations, const declarations are hoisted to function -@@ -2113,9 +2114,12 @@ void FullCodeGenerator::EmitResolvePossiblyDirectEval(ResolveEvalFlag flag, - // Push the strict mode flag. - __ push(Immediate(Smi::FromInt(strict_mode_flag()))); +@@ -2147,9 +2148,12 @@ void FullCodeGenerator::EmitResolvePossiblyDirectEval(ResolveEvalFlag flag, + } + __ push(Immediate(Smi::FromInt(strict_mode))); + // Push the qml mode flag + __ push(Immediate(Smi::FromInt(is_qml_mode()))); @@ -981,22 +994,41 @@ index 5d153a8..0ddcde2 100644 } -@@ -2188,8 +2192,8 @@ void FullCodeGenerator::VisitCall(Call* expr) { - context()->DropAndPlug(1, eax); - } else if (var != NULL && !var->is_this() && var->is_global()) { +@@ -2220,9 +2224,9 @@ void FullCodeGenerator::VisitCall(Call* expr) { + + } else if (proxy != NULL && proxy->var()->IsUnallocated()) { // Push global object as receiver for the call IC. - __ push(GlobalObjectOperand()); -- EmitCallWithIC(expr, var->name(), RelocInfo::CODE_TARGET_CONTEXT); -+ __ push(var->is_qml_global()?QmlGlobalObjectOperand():GlobalObjectOperand()); -+ EmitCallWithIC(expr, var->name(), var->is_qml_global()?RelocInfo::CODE_TARGET:RelocInfo::CODE_TARGET_CONTEXT); - } else if (var != NULL && var->AsSlot() != NULL && - var->AsSlot()->type() == Slot::LOOKUP) { ++ __ push(proxy->var()->is_qml_global()?QmlGlobalObjectOperand():GlobalObjectOperand()); + increment_stack_height(); +- EmitCallWithIC(expr, proxy->name(), RelocInfo::CODE_TARGET_CONTEXT); ++ EmitCallWithIC(expr, proxy->name(), proxy->var()->is_qml_global()?RelocInfo::CODE_TARGET:RelocInfo::CODE_TARGET_CONTEXT); + + } else if (proxy != NULL && proxy->var()->IsLookupSlot()) { // Call to a lookup slot (dynamically introduced variable). +@@ -3688,7 +3692,7 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { + // but "delete this" is allowed. + ASSERT(strict_mode_flag() == kNonStrictMode || var->is_this()); + if (var->IsUnallocated()) { +- __ push(GlobalObjectOperand()); ++ __ push(var->is_qml_global() ? QmlGlobalObjectOperand() : GlobalObjectOperand()); + __ push(Immediate(var->name())); + __ push(Immediate(Smi::FromInt(kNonStrictMode))); + __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION); +@@ -3996,7 +4000,7 @@ void FullCodeGenerator::VisitForTypeofValue(Expression* expr) { + + if (proxy != NULL && proxy->var()->IsUnallocated()) { + Comment cmnt(masm_, "Global variable"); +- __ mov(eax, GlobalObjectOperand()); ++ __ mov(eax, proxy->var()->is_qml_global() ? QmlGlobalObjectOperand() : GlobalObjectOperand()); + __ mov(ecx, Immediate(proxy->name())); + Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); + // Use a regular load, not a contextual load, to avoid a reference diff --git a/src/ia32/lithium-codegen-ia32.cc b/src/ia32/lithium-codegen-ia32.cc -index 0f96f78..c1da075 100644 +index 9e1fd34..1abcdd3 100644 --- a/src/ia32/lithium-codegen-ia32.cc +++ b/src/ia32/lithium-codegen-ia32.cc -@@ -159,12 +159,13 @@ bool LCodeGen::GeneratePrologue() { +@@ -211,12 +211,13 @@ bool LCodeGen::GeneratePrologue() { // Possibly allocate a local context. int heap_slots = scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; @@ -1011,8 +1043,8 @@ index 0f96f78..c1da075 100644 + FastNewContextStub stub((heap_slots < 0)?0:heap_slots); __ CallStub(&stub); } else { - __ CallRuntime(Runtime::kNewContext, 1); -@@ -2525,7 +2526,7 @@ void LCodeGen::DoOuterContext(LOuterContext* instr) { + __ CallRuntime(Runtime::kNewFunctionContext, 1); +@@ -2635,7 +2636,7 @@ void LCodeGen::DoOuterContext(LOuterContext* instr) { void LCodeGen::DoGlobalObject(LGlobalObject* instr) { Register context = ToRegister(instr->context()); Register result = ToRegister(instr->result()); @@ -1022,10 +1054,10 @@ index 0f96f78..c1da075 100644 diff --git a/src/ia32/lithium-ia32.cc b/src/ia32/lithium-ia32.cc -index 9ccd189..8e98b73 100644 +index 856106c..0b058e6 100644 --- a/src/ia32/lithium-ia32.cc +++ b/src/ia32/lithium-ia32.cc -@@ -1205,7 +1205,7 @@ LInstruction* LChunkBuilder::DoOuterContext(HOuterContext* instr) { +@@ -1138,7 +1138,7 @@ LInstruction* LChunkBuilder::DoOuterContext(HOuterContext* instr) { LInstruction* LChunkBuilder::DoGlobalObject(HGlobalObject* instr) { LOperand* context = UseRegisterAtStart(instr->value()); @@ -1035,10 +1067,10 @@ index 9ccd189..8e98b73 100644 diff --git a/src/ia32/lithium-ia32.h b/src/ia32/lithium-ia32.h -index 9ace8f8..95ed001 100644 +index 3a06ac3..087d5cb 100644 --- a/src/ia32/lithium-ia32.h +++ b/src/ia32/lithium-ia32.h -@@ -1416,13 +1416,17 @@ class LOuterContext: public LTemplateInstruction<1, 1, 0> { +@@ -1336,13 +1336,17 @@ class LOuterContext: public LTemplateInstruction<1, 1, 0> { class LGlobalObject: public LTemplateInstruction<1, 1, 0> { public: @@ -1058,82 +1090,69 @@ index 9ace8f8..95ed001 100644 diff --git a/src/ia32/macro-assembler-ia32.h b/src/ia32/macro-assembler-ia32.h -index b986264..f8479ae 100644 +index a1b42c2..7a64b9a 100644 --- a/src/ia32/macro-assembler-ia32.h +++ b/src/ia32/macro-assembler-ia32.h -@@ -778,6 +778,11 @@ static inline Operand GlobalObjectOperand() { +@@ -931,6 +931,9 @@ static inline Operand GlobalObjectOperand() { + return ContextOperand(esi, Context::GLOBAL_INDEX); } - +static inline Operand QmlGlobalObjectOperand() { + return ContextOperand(esi, Context::QML_GLOBAL_INDEX); +} -+ -+ + // Generates an Operand for saving parameters after PrepareCallApiFunction. Operand ApiParameterOperand(int index); - diff --git a/src/objects-inl.h b/src/objects-inl.h -index 231b835..1c7f83e 100644 +index 36af868..375df0f 100644 --- a/src/objects-inl.h +++ b/src/objects-inl.h -@@ -3242,6 +3242,18 @@ void SharedFunctionInfo::set_strict_mode(bool value) { - } - - -+bool SharedFunctionInfo::qml_mode() { -+ return BooleanBit::get(compiler_hints(), kQmlModeFunction); -+} -+ -+ -+void SharedFunctionInfo::set_qml_mode(bool value) { -+ set_compiler_hints(BooleanBit::set(compiler_hints(), -+ kQmlModeFunction, -+ value)); -+} -+ -+ - ACCESSORS(CodeCache, default_cache, FixedArray, kDefaultCacheOffset) - ACCESSORS(CodeCache, normal_type_cache, Object, kNormalTypeCacheOffset) - +@@ -3615,6 +3615,8 @@ void SharedFunctionInfo::set_optimization_disabled(bool disable) { + + BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, strict_mode, + kStrictModeFunction) ++BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, qml_mode, ++ kQmlModeFunction) + BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, native, kNative) + BOOL_ACCESSORS(SharedFunctionInfo, compiler_hints, + name_should_print_as_anonymous, diff --git a/src/objects.h b/src/objects.h -index 1bdb5c7..edbc47a 100644 +index dea5bbd..71895be 100644 --- a/src/objects.h +++ b/src/objects.h -@@ -4331,6 +4331,10 @@ class SharedFunctionInfo: public HeapObject { - inline bool strict_mode(); - inline void set_strict_mode(bool value); +@@ -4725,6 +4725,9 @@ class SharedFunctionInfo: public HeapObject { + // Indicates whether the function is a strict mode function. + DECL_BOOLEAN_ACCESSORS(strict_mode) -+ // Indicates whether the function is a qml mode function -+ inline bool qml_mode(); -+ inline void set_qml_mode(bool value); ++ // Indicates whether the function is a qml mode function. ++ DECL_BOOLEAN_ACCESSORS(qml_mode) + - // Indicates whether or not the code in the shared function support - // deoptimization. - inline bool has_deoptimization_support(); -@@ -4511,6 +4515,7 @@ class SharedFunctionInfo: public HeapObject { - static const int kCodeAgeMask = 0x7; - static const int kOptimizationDisabled = 6; - static const int kStrictModeFunction = 7; -+ static const int kQmlModeFunction = 8; - - private: - #if V8_HOST_ARCH_32_BIT + // False if the function definitely does not allocate an arguments object. + DECL_BOOLEAN_ACCESSORS(uses_arguments) + +@@ -4939,6 +4942,7 @@ class SharedFunctionInfo: public HeapObject { + kCodeAgeShift, + kOptimizationDisabled = kCodeAgeShift + kCodeAgeSize, + kStrictModeFunction, ++ kQmlModeFunction, + kUsesArguments, + kHasDuplicateParameters, + kNative, diff --git a/src/parser.cc b/src/parser.cc -index a84ec6f..7f5c361 100644 +index ad8850e..a9af8eb 100644 --- a/src/parser.cc +++ b/src/parser.cc -@@ -593,7 +593,8 @@ Parser::Parser(Handle<Script> script, +@@ -594,7 +594,8 @@ Parser::Parser(Handle<Script> script, FunctionLiteral* Parser::ParseProgram(Handle<String> source, bool in_global_context, - StrictModeFlag strict_mode) { + StrictModeFlag strict_mode, + bool qml_mode) { - CompilationZoneScope zone_scope(DONT_DELETE_ON_EXIT); + ZoneScope zone_scope(isolate(), DONT_DELETE_ON_EXIT); HistogramTimerScope timer(isolate()->counters()->parse()); -@@ -609,11 +610,11 @@ FunctionLiteral* Parser::ParseProgram(Handle<String> source, +@@ -610,11 +611,11 @@ FunctionLiteral* Parser::ParseProgram(Handle<String> source, ExternalTwoByteStringUC16CharacterStream stream( Handle<ExternalTwoByteString>::cast(source), 0, source->length()); scanner_.Initialize(&stream); @@ -1147,7 +1166,7 @@ index a84ec6f..7f5c361 100644 } } -@@ -621,6 +622,7 @@ FunctionLiteral* Parser::ParseProgram(Handle<String> source, +@@ -622,6 +623,7 @@ FunctionLiteral* Parser::ParseProgram(Handle<String> source, FunctionLiteral* Parser::DoParseProgram(Handle<String> source, bool in_global_context, StrictModeFlag strict_mode, @@ -1155,17 +1174,17 @@ index a84ec6f..7f5c361 100644 ZoneScope* zone_scope) { ASSERT(target_stack_ == NULL); if (pre_data_ != NULL) pre_data_->Initialize(); -@@ -641,6 +643,9 @@ FunctionLiteral* Parser::DoParseProgram(Handle<String> source, +@@ -642,6 +644,9 @@ FunctionLiteral* Parser::DoParseProgram(Handle<String> source, if (strict_mode == kStrictMode) { top_scope_->EnableStrictMode(); } + if (qml_mode) { + scope->EnableQmlMode(); + } - ZoneList<Statement*>* body = new ZoneList<Statement*>(16); + ZoneList<Statement*>* body = new(zone()) ZoneList<Statement*>(16); bool ok = true; int beg_loc = scanner().location().beg_pos; -@@ -729,6 +734,9 @@ FunctionLiteral* Parser::ParseLazy(CompilationInfo* info, +@@ -736,6 +741,9 @@ FunctionLiteral* Parser::ParseLazy(CompilationInfo* info, if (shared_info->strict_mode()) { top_scope_->EnableStrictMode(); } @@ -1173,9 +1192,9 @@ index a84ec6f..7f5c361 100644 + top_scope_->EnableQmlMode(); + } - FunctionLiteralType type = - shared_info->is_expression() ? EXPRESSION : DECLARATION; -@@ -1661,6 +1669,11 @@ Block* Parser::ParseVariableDeclarations(bool accept_IN, + FunctionLiteral::Type type = shared_info->is_expression() + ? (shared_info->is_anonymous() +@@ -1806,6 +1814,11 @@ Block* Parser::ParseVariableDeclarations(VariableDeclarationContext var_context, arguments->Add(value); value = NULL; // zap the value to avoid the unnecessary assignment @@ -1187,9 +1206,9 @@ index a84ec6f..7f5c361 100644 // Construct the call to Runtime_InitializeConstGlobal // and add it to the initialization statement block. // Note that the function does different things depending on -@@ -1676,6 +1689,11 @@ Block* Parser::ParseVariableDeclarations(bool accept_IN, - arguments->Add(NewNumberLiteral( - top_scope_->is_strict_mode() ? kStrictMode : kNonStrictMode)); +@@ -1824,6 +1837,11 @@ Block* Parser::ParseVariableDeclarations(VariableDeclarationContext var_context, + : kNonStrictMode; + arguments->Add(NewNumberLiteral(flag)); + int qml_mode = 0; + if (top_scope_->is_qml_mode() && !Isolate::Current()->global()->HasProperty(*name)) @@ -1199,7 +1218,7 @@ index a84ec6f..7f5c361 100644 // Be careful not to assign a value to the global variable if // we're in a with. The initialization value should not // necessarily be stored in the global object in that case, -@@ -5157,7 +5175,8 @@ bool ParserApi::Parse(CompilationInfo* info) { +@@ -5217,7 +5235,8 @@ bool ParserApi::Parse(CompilationInfo* info) { Handle<String> source = Handle<String>(String::cast(script->source())); result = parser.ParseProgram(source, info->is_global(), @@ -1208,12 +1227,12 @@ index a84ec6f..7f5c361 100644 + info->is_qml_mode()); } } - + info->SetFunction(result); diff --git a/src/parser.h b/src/parser.h -index 64f1303..4d45e45 100644 +index d834ed1..d88d1ef 100644 --- a/src/parser.h +++ b/src/parser.h -@@ -431,7 +431,8 @@ class Parser { +@@ -426,7 +426,8 @@ class Parser { // Returns NULL if parsing failed. FunctionLiteral* ParseProgram(Handle<String> source, bool in_global_context, @@ -1223,7 +1242,7 @@ index 64f1303..4d45e45 100644 FunctionLiteral* ParseLazy(CompilationInfo* info); -@@ -464,6 +465,7 @@ class Parser { +@@ -466,6 +467,7 @@ class Parser { FunctionLiteral* DoParseProgram(Handle<String> source, bool in_global_context, StrictModeFlag strict_mode, @@ -1232,10 +1251,10 @@ index 64f1303..4d45e45 100644 // Report syntax error diff --git a/src/prettyprinter.cc b/src/prettyprinter.cc -index c777ab4..1964e02 100644 +index 37c76ce..73812fd 100644 --- a/src/prettyprinter.cc +++ b/src/prettyprinter.cc -@@ -656,6 +656,9 @@ void AstPrinter::PrintLiteralWithModeIndented(const char* info, +@@ -618,6 +618,9 @@ void AstPrinter::PrintLiteralWithModeIndented(const char* info, EmbeddedVector<char, 256> buf; int pos = OS::SNPrintF(buf, "%s (mode = %s", info, Variable::Mode2String(var->mode())); @@ -1246,30 +1265,23 @@ index c777ab4..1964e02 100644 PrintLiteralIndented(buf.start(), value, true); } diff --git a/src/runtime.cc b/src/runtime.cc -index 660352c..c13f92d 100644 +index 5a850e9..0388a77 100644 --- a/src/runtime.cc +++ b/src/runtime.cc -@@ -1065,8 +1065,6 @@ static Failure* ThrowRedeclarationError(Isolate* isolate, +@@ -1213,19 +1213,23 @@ static Failure* ThrowRedeclarationError(Isolate* isolate, RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareGlobals) { - ASSERT(args.length() == 4); + ASSERT(args.length() == 3); HandleScope scope(isolate); - Handle<GlobalObject> global = Handle<GlobalObject>( - isolate->context()->global()); Handle<Context> context = args.at<Context>(0); CONVERT_ARG_CHECKED(FixedArray, pairs, 1); -@@ -1075,6 +1073,9 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareGlobals) { - static_cast<StrictModeFlag>(Smi::cast(args[3])->value()); - ASSERT(strict_mode == kStrictMode || strict_mode == kNonStrictMode); + CONVERT_SMI_ARG_CHECKED(flags, 2); + Handle<JSObject> js_global = Handle<JSObject>(isolate->context()->global()); + Handle<JSObject> qml_global = Handle<JSObject>(isolate->context()->qml_global()); + - // Compute the property attributes. According to ECMA-262, section - // 13, page 71, the property must be read-only and - // non-deletable. However, neither SpiderMonkey nor KJS creates the -@@ -1083,10 +1084,13 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareGlobals) { - // Traverse the name/value pairs and set the properties. int length = pairs->length(); - for (int i = 0; i < length; i += 2) { @@ -1283,7 +1295,7 @@ index 660352c..c13f92d 100644 // We have to declare a global const property. To capture we only // assign to it when evaluating the assignment for "const x = -@@ -1316,20 +1320,25 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeVarGlobal) { +@@ -1414,19 +1418,24 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeVarGlobal) { NoHandleAllocation nha; // args[0] == name // args[1] == strict_mode @@ -1301,8 +1313,7 @@ index 660352c..c13f92d 100644 CONVERT_ARG_CHECKED(String, name, 0); - GlobalObject* global = isolate->context()->global(); RUNTIME_ASSERT(args[1]->IsSmi()); - StrictModeFlag strict_mode = - static_cast<StrictModeFlag>(Smi::cast(args[1])->value()); + StrictModeFlag strict_mode = static_cast<StrictModeFlag>(args.smi_at(1)); ASSERT(strict_mode == kStrictMode || strict_mode == kNonStrictMode); + RUNTIME_ASSERT(args[2]->IsSmi()); @@ -1313,37 +1324,19 @@ index 660352c..c13f92d 100644 // According to ECMA-262, section 12.2, page 62, the property must // not be deletable. PropertyAttributes attributes = DONT_DELETE; -@@ -1350,7 +1359,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeVarGlobal) { - if (lookup.IsReadOnly()) { - // If we found readonly property on one of hidden prototypes, - // just shadow it. -- if (real_holder != isolate->context()->global()) break; -+ if (real_holder != global) break; - return ThrowRedeclarationError(isolate, "const", name); - } - -@@ -1372,7 +1381,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeVarGlobal) { - // overwrite it with a variable declaration we must throw a - // re-declaration error. However if we found readonly property - // on one of hidden prototypes, just shadow it. -- if (real_holder != isolate->context()->global()) break; -+ if (real_holder != global) break; - return ThrowRedeclarationError(isolate, "const", name); +@@ -1454,7 +1463,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeVarGlobal) { + // Found an interceptor that's not read only. + if (assign) { + return raw_holder->SetProperty( +- &lookup, *name, args[2], attributes, strict_mode); ++ &lookup, *name, args[3], attributes, strict_mode); + } else { + return isolate->heap()->undefined_value(); } - } -@@ -1384,7 +1393,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeVarGlobal) { - } - - // Assign the value (or undefined) to the property. -- Object* value = (assign) ? args[2] : isolate->heap()->undefined_value(); -+ Object* value = (assign) ? args[3] : isolate->heap()->undefined_value(); - return real_holder->SetProperty( - &lookup, *name, value, attributes, strict_mode); - } -@@ -1399,9 +1408,9 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeVarGlobal) { - real_holder = JSObject::cast(proto); +@@ -1464,9 +1473,9 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeVarGlobal) { } + // Reload global in case the loop above performed a GC. - global = isolate->context()->global(); + global = qml_mode?isolate->context()->qml_global():isolate->context()->global(); if (assign) { @@ -1352,7 +1345,7 @@ index 660352c..c13f92d 100644 } return isolate->heap()->undefined_value(); } -@@ -1411,12 +1420,15 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeConstGlobal) { +@@ -1476,12 +1485,15 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeConstGlobal) { // All constants are declared with an initial value. The name // of the constant is the first argument and the initial value // is the second. @@ -1370,16 +1363,16 @@ index 660352c..c13f92d 100644 // According to ECMA-262, section 12.2, page 62, the property must // not be deletable. Since it's a const, it must be READ_ONLY too. -@@ -1456,7 +1468,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeConstGlobal) { - // with setting the value because the property is either absent or - // read-only. We also have to do redo the lookup. +@@ -1505,7 +1517,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeConstGlobal) { + // Restore global object from context (in case of GC) and continue + // with setting the value. HandleScope handle_scope(isolate); - Handle<GlobalObject> global(isolate->context()->global()); + Handle<JSObject> global(qml_mode?isolate->context()->qml_global():isolate->context()->global()); // BUG 1213575: Handle the case where we have to set a read-only // property through an interceptor and only do it if it's -@@ -8160,7 +8172,8 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_CompileString) { +@@ -9204,7 +9216,8 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_CompileString) { Handle<SharedFunctionInfo> shared = Compiler::CompileEval(source, context, true, @@ -1389,26 +1382,27 @@ index 660352c..c13f92d 100644 if (shared.is_null()) return Failure::Exception(); Handle<JSFunction> fun = isolate->factory()->NewFunctionFromSharedFunctionInfo(shared, -@@ -8173,14 +8186,16 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_CompileString) { +@@ -9217,7 +9230,8 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_CompileString) { static ObjectPair CompileGlobalEval(Isolate* isolate, Handle<String> source, Handle<Object> receiver, - StrictModeFlag strict_mode) { -+ StrictModeFlag strict_mode, ++ StrictModeFlag strict_mode, + bool qml_mode) { - // Deal with a normal eval call with a string argument. Compile it - // and return the compiled function bound in the local context. - Handle<SharedFunctionInfo> shared = Compiler::CompileEval( + Handle<Context> context = Handle<Context>(isolate->context()); + Handle<Context> global_context = Handle<Context>(context->global_context()); + +@@ -9235,7 +9249,8 @@ static ObjectPair CompileGlobalEval(Isolate* isolate, source, Handle<Context>(isolate->context()), - isolate->context()->IsGlobalContext(), + context->IsGlobalContext(), - strict_mode); + strict_mode, -+ qml_mode); ++ qml_mode); if (shared.is_null()) return MakePair(Failure::Exception(), NULL); Handle<JSFunction> compiled = isolate->factory()->NewFunctionFromSharedFunctionInfo( -@@ -8190,7 +8205,7 @@ static ObjectPair CompileGlobalEval(Isolate* isolate, +@@ -9245,7 +9260,7 @@ static ObjectPair CompileGlobalEval(Isolate* isolate, RUNTIME_FUNCTION(ObjectPair, Runtime_ResolvePossiblyDirectEval) { @@ -1417,7 +1411,7 @@ index 660352c..c13f92d 100644 HandleScope scope(isolate); Handle<Object> callee = args.at<Object>(0); -@@ -8257,16 +8272,18 @@ RUNTIME_FUNCTION(ObjectPair, Runtime_ResolvePossiblyDirectEval) { +@@ -9308,15 +9323,17 @@ RUNTIME_FUNCTION(ObjectPair, Runtime_ResolvePossiblyDirectEval) { } ASSERT(args[3]->IsSmi()); @@ -1425,9 +1419,8 @@ index 660352c..c13f92d 100644 return CompileGlobalEval(isolate, args.at<String>(1), args.at<Object>(2), - static_cast<StrictModeFlag>( -- Smi::cast(args[3])->value())); -+ Smi::cast(args[3])->value()), +- static_cast<StrictModeFlag>(args.smi_at(3))); ++ static_cast<StrictModeFlag>(args.smi_at(3)), + Smi::cast(args[4])->value()); } @@ -1438,7 +1431,7 @@ index 660352c..c13f92d 100644 HandleScope scope(isolate); Handle<Object> callee = args.at<Object>(0); -@@ -8280,11 +8297,13 @@ RUNTIME_FUNCTION(ObjectPair, Runtime_ResolvePossiblyDirectEvalNoLookup) { +@@ -9329,10 +9346,12 @@ RUNTIME_FUNCTION(ObjectPair, Runtime_ResolvePossiblyDirectEvalNoLookup) { } ASSERT(args[3]->IsSmi()); @@ -1446,14 +1439,13 @@ index 660352c..c13f92d 100644 return CompileGlobalEval(isolate, args.at<String>(1), args.at<Object>(2), - static_cast<StrictModeFlag>( -- Smi::cast(args[3])->value())); -+ Smi::cast(args[3])->value()), +- static_cast<StrictModeFlag>(args.smi_at(3))); ++ static_cast<StrictModeFlag>(args.smi_at(3)), + Smi::cast(args[4])->value()); } -@@ -10570,6 +10589,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugEvaluate) { +@@ -11771,6 +11790,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugEvaluate) { Handle<JSFunction> function(JSFunction::cast(frame->function())); Handle<SerializedScopeInfo> scope_info(function->shared()->scope_info()); ScopeInfo<> sinfo(*scope_info); @@ -1461,7 +1453,7 @@ index 660352c..c13f92d 100644 // Traverse the saved contexts chain to find the active context for the // selected frame. -@@ -10633,7 +10653,8 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugEvaluate) { +@@ -11840,7 +11860,8 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugEvaluate) { Compiler::CompileEval(function_source, context, context->IsGlobalContext(), @@ -1471,17 +1463,17 @@ index 660352c..c13f92d 100644 if (shared.is_null()) return Failure::Exception(); Handle<JSFunction> compiled_function = isolate->factory()->NewFunctionFromSharedFunctionInfo(shared, context); -@@ -10656,7 +10677,8 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugEvaluate) { - Handle<Object>::cast(source).location() }; - Handle<Object> result = - Execution::Call(Handle<JSFunction>::cast(evaluation_function), receiver, -- argc, argv, &has_pending_exception); -+ argc, argv, &has_pending_exception, +@@ -11850,7 +11871,8 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugEvaluate) { + Handle<Object> receiver(frame->receiver(), isolate); + Handle<Object> evaluation_function = + Execution::Call(compiled_function, receiver, 0, NULL, +- &has_pending_exception); ++ &has_pending_exception, false, + Handle<Object>(function->context()->qml_global())); if (has_pending_exception) return Failure::Exception(); - // Skip the global proxy as it has no properties and always delegates to the -@@ -10722,7 +10744,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugEvaluateGlobal) { + Handle<Object> arguments = GetArgumentsObject(isolate, +@@ -11930,7 +11952,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugEvaluateGlobal) { // Currently, the eval code will be executed in non-strict mode, // even in the strict code context. Handle<SharedFunctionInfo> shared = @@ -1491,10 +1483,10 @@ index 660352c..c13f92d 100644 Handle<JSFunction> compiled_function = Handle<JSFunction>( diff --git a/src/runtime.h b/src/runtime.h -index bf1ba68..5e97173 100644 +index c6f7773..284f723 100644 --- a/src/runtime.h +++ b/src/runtime.h -@@ -241,8 +241,8 @@ namespace internal { +@@ -257,8 +257,8 @@ namespace internal { \ /* Eval */ \ F(GlobalReceiver, 1, 1) \ @@ -1505,9 +1497,9 @@ index bf1ba68..5e97173 100644 \ F(SetProperty, -1 /* 4 or 5 */, 1) \ F(DefineOrRedefineDataProperty, 4, 1) \ -@@ -296,8 +296,8 @@ namespace internal { +@@ -325,8 +325,8 @@ namespace internal { /* Declarations and initialization */ \ - F(DeclareGlobals, 4, 1) \ + F(DeclareGlobals, 3, 1) \ F(DeclareContextSlot, 4, 1) \ - F(InitializeVarGlobal, -1 /* 2 or 3 */, 1) \ - F(InitializeConstGlobal, 2, 1) \ @@ -1517,18 +1509,27 @@ index bf1ba68..5e97173 100644 F(OptimizeObjectForAddingMultipleProperties, 2, 1) \ \ diff --git a/src/scopes.cc b/src/scopes.cc -index 8df93c5..b5d7ff3 100644 +index d5a7a9f..25921fa 100644 --- a/src/scopes.cc +++ b/src/scopes.cc -@@ -198,6 +198,7 @@ void Scope::SetDefaults(Type type, +@@ -35,6 +35,8 @@ + + #include "allocation-inl.h" + ++#include "debug.h" ++ + namespace v8 { + namespace internal { + +@@ -202,6 +204,7 @@ void Scope::SetDefaults(Type type, scope_calls_eval_ = false; // Inherit the strict mode from the parent scope. strict_mode_ = (outer_scope != NULL) && outer_scope->strict_mode_; + qml_mode_ = (outer_scope != NULL) && outer_scope->qml_mode_; outer_scope_calls_eval_ = false; + outer_scope_calls_non_strict_eval_ = false; inner_scope_calls_eval_ = false; - outer_scope_is_eval_scope_ = false; -@@ -796,6 +797,25 @@ void Scope::ResolveVariable(Scope* global_scope, +@@ -923,6 +926,25 @@ void Scope::ResolveVariable(Scope* global_scope, ASSERT(global_scope != NULL); var = global_scope->DeclareGlobal(proxy->name()); @@ -1554,7 +1555,7 @@ index 8df93c5..b5d7ff3 100644 } else if (scope_inside_with_) { // If we are inside a with statement we give up and look up // the variable at runtime. -@@ -817,6 +837,25 @@ void Scope::ResolveVariable(Scope* global_scope, +@@ -944,6 +966,25 @@ void Scope::ResolveVariable(Scope* global_scope, if (context->GlobalIfNotShadowedByEval(proxy->name())) { var = NonLocal(proxy->name(), Variable::DYNAMIC_GLOBAL); @@ -1580,7 +1581,7 @@ index 8df93c5..b5d7ff3 100644 } else { var = NonLocal(proxy->name(), Variable::DYNAMIC); } -@@ -827,6 +866,26 @@ void Scope::ResolveVariable(Scope* global_scope, +@@ -954,6 +995,26 @@ void Scope::ResolveVariable(Scope* global_scope, // variable is global unless it is shadowed by eval-introduced // variables. var = NonLocal(proxy->name(), Variable::DYNAMIC_GLOBAL); @@ -1608,10 +1609,10 @@ index 8df93c5..b5d7ff3 100644 } } diff --git a/src/scopes.h b/src/scopes.h -index a0e56a4..6dd3f65 100644 +index 2917a63..0f1ed6d 100644 --- a/src/scopes.h +++ b/src/scopes.h -@@ -210,6 +210,11 @@ class Scope: public ZoneObject { +@@ -206,6 +206,11 @@ class Scope: public ZoneObject { strict_mode_ = FLAG_strict_mode; } @@ -1623,28 +1624,29 @@ index a0e56a4..6dd3f65 100644 // --------------------------------------------------------------------------- // Predicates. -@@ -218,6 +223,7 @@ class Scope: public ZoneObject { - bool is_function_scope() const { return type_ == FUNCTION_SCOPE; } - bool is_global_scope() const { return type_ == GLOBAL_SCOPE; } +@@ -216,6 +221,7 @@ class Scope: public ZoneObject { + bool is_catch_scope() const { return type_ == CATCH_SCOPE; } + bool is_block_scope() const { return type_ == BLOCK_SCOPE; } bool is_strict_mode() const { return strict_mode_; } + bool is_qml_mode() const { return qml_mode_; } - - // Information about which scopes calls eval. - bool calls_eval() const { return scope_calls_eval_; } -@@ -376,6 +382,7 @@ class Scope: public ZoneObject { - bool scope_contains_with_; // this scope contains a 'with' statement - bool scope_calls_eval_; // this scope contains an 'eval' call - bool strict_mode_; // this scope is a strict mode scope -+ bool qml_mode_; // this scope is a qml mode scope + bool is_strict_mode_eval_scope() const { + return is_eval_scope() && is_strict_mode(); + } +@@ -381,6 +387,8 @@ class Scope: public ZoneObject { + bool scope_calls_eval_; + // This scope is a strict mode scope. + bool strict_mode_; ++ // This scope is a qml mode scope. ++ bool qml_mode_; // Computed via PropagateScopeInfo. bool outer_scope_calls_eval_; diff --git a/src/variables.cc b/src/variables.cc -index 0502722..190baf6 100644 +index 971061b..da07620 100644 --- a/src/variables.cc +++ b/src/variables.cc -@@ -99,7 +99,8 @@ Variable::Variable(Scope* scope, - rewrite_(NULL), +@@ -67,7 +67,8 @@ Variable::Variable(Scope* scope, + local_if_not_shadowed_(NULL), is_valid_LHS_(is_valid_LHS), is_accessed_from_inner_scope_(false), - is_used_(false) { @@ -1654,19 +1656,19 @@ index 0502722..190baf6 100644 ASSERT(name->IsSymbol()); } diff --git a/src/variables.h b/src/variables.h -index b1ff0db..0b31d1a 100644 +index 56c8dab..4d27f98 100644 --- a/src/variables.h +++ b/src/variables.h -@@ -141,6 +141,8 @@ class Variable: public ZoneObject { - Expression* rewrite() const { return rewrite_; } - void set_rewrite(Expression* expr) { rewrite_ = expr; } +@@ -174,6 +174,8 @@ class Variable: public ZoneObject { + index_ = index; + } + bool is_qml_global() const { return is_qml_global_; } + void set_is_qml_global(bool is_qml_global) { is_qml_global_ = is_qml_global; } private: Scope* scope_; Handle<String> name_; -@@ -159,6 +161,9 @@ class Variable: public ZoneObject { +@@ -190,6 +192,9 @@ class Variable: public ZoneObject { // Usage info. bool is_accessed_from_inner_scope_; // set by variable resolver bool is_used_; @@ -1677,14 +1679,14 @@ index b1ff0db..0b31d1a 100644 diff --git a/src/x64/code-stubs-x64.cc b/src/x64/code-stubs-x64.cc -index c365385..d923494 100644 +index 8d9dba7..6ab12fc 100644 --- a/src/x64/code-stubs-x64.cc +++ b/src/x64/code-stubs-x64.cc -@@ -140,6 +140,10 @@ void FastNewContextStub::Generate(MacroAssembler* masm) { +@@ -139,6 +139,10 @@ void FastNewContextStub::Generate(MacroAssembler* masm) { __ movq(rbx, Operand(rsi, Context::SlotOffset(Context::GLOBAL_INDEX))); __ movq(Operand(rax, Context::SlotOffset(Context::GLOBAL_INDEX)), rbx); -+ // Copy the qml global object from the surrounding context. ++ // Copy the qmlglobal object from the previous context. + __ movq(rbx, Operand(rsi, Context::SlotOffset(Context::QML_GLOBAL_INDEX))); + __ movq(Operand(rax, Context::SlotOffset(Context::QML_GLOBAL_INDEX)), rbx); + @@ -1692,15 +1694,15 @@ 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..c45cdb6 100644 +index 1d9b8ff..08b3872 100644 --- a/src/x64/full-codegen-x64.cc +++ b/src/x64/full-codegen-x64.cc -@@ -141,12 +141,13 @@ void FullCodeGenerator::Generate(CompilationInfo* info) { +@@ -173,12 +173,13 @@ void FullCodeGenerator::Generate(CompilationInfo* info) { // Possibly allocate a local context. - int heap_slots = scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; + int heap_slots = info->scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; - if (heap_slots > 0) { -+ 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. @@ -1710,49 +1712,44 @@ index 97168cd..c45cdb6 100644 + FastNewContextStub stub((heap_slots < 0)?0:heap_slots); __ CallStub(&stub); } else { - __ CallRuntime(Runtime::kNewContext, 1); -@@ -1119,10 +1120,10 @@ void FullCodeGenerator::EmitLoadGlobalSlotCheckExtensions( + __ CallRuntime(Runtime::kNewFunctionContext, 1); +@@ -1129,10 +1130,10 @@ void FullCodeGenerator::EmitLoadGlobalCheckExtensions(Variable* var, // All extension objects were empty and it is safe to use a global // load IC call. - __ movq(rax, GlobalObjectOperand()); -+ __ movq(rax, slot->var()->is_qml_global() ? QmlGlobalObjectOperand() : GlobalObjectOperand()); - __ Move(rcx, slot->var()->name()); ++ __ movq(rax, var->is_qml_global() ? QmlGlobalObjectOperand() : GlobalObjectOperand()); + __ Move(rcx, var->name()); Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); - RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF) -+ RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF || slot->var()->is_qml_global()) ++ RelocInfo::Mode mode = (typeof_state == INSIDE_TYPEOF || var->is_qml_global()) ? RelocInfo::CODE_TARGET : RelocInfo::CODE_TARGET_CONTEXT; - EmitCallIC(ic, mode); -@@ -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()); -- __ movq(rax, GlobalObjectOperand()); -+ __ movq(rax, var->is_qml_global() ? QmlGlobalObjectOperand() : GlobalObjectOperand()); - Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); -- EmitCallIC(ic, RelocInfo::CODE_TARGET_CONTEXT); -+ EmitCallIC(ic, var->is_qml_global() ? RelocInfo::CODE_TARGET : RelocInfo::CODE_TARGET_CONTEXT); - context()->Plug(rax); - - } else if (slot != NULL && slot->type() == Slot::LOOKUP) { -@@ -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. + __ call(ic, mode); +@@ -1207,9 +1208,9 @@ void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy) { + // Use inline caching. Variable name is passed in rcx and the global + // object on the stack. + __ Move(rcx, var->name()); +- __ movq(rax, GlobalObjectOperand()); ++ __ movq(rax, var->is_qml_global() ? QmlGlobalObjectOperand() : GlobalObjectOperand()); + Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); +- __ call(ic, RelocInfo::CODE_TARGET_CONTEXT); ++ __ call(ic, var->is_qml_global() ? RelocInfo::CODE_TARGET : RelocInfo::CODE_TARGET_CONTEXT); + context()->Plug(rax); + break; + } +@@ -1750,7 +1751,7 @@ void FullCodeGenerator::EmitVariableAssignment(Variable* var, + if (var->IsUnallocated()) { + // Global var, const, or let. __ Move(rcx, var->name()); - __ movq(rdx, GlobalObjectOperand()); + __ movq(rdx, var->is_qml_global() ? QmlGlobalObjectOperand() : GlobalObjectOperand()); Handle<Code> ic = is_strict_mode() ? isolate()->builtins()->StoreIC_Initialize_Strict() : isolate()->builtins()->StoreIC_Initialize(); -- EmitCallIC(ic, RelocInfo::CODE_TARGET_CONTEXT); -+ EmitCallIC(ic, var->is_qml_global() ? RelocInfo::CODE_TARGET : RelocInfo::CODE_TARGET_CONTEXT); - - } else if (op == Token::INIT_CONST) { - // Like var declarations, const declarations are hoisted to function -@@ -2085,9 +2086,12 @@ void FullCodeGenerator::EmitResolvePossiblyDirectEval(ResolveEvalFlag flag, - // Push the strict mode flag. - __ Push(Smi::FromInt(strict_mode_flag())); +@@ -2034,9 +2035,12 @@ void FullCodeGenerator::EmitResolvePossiblyDirectEval(ResolveEvalFlag flag, + } + __ Push(Smi::FromInt(strict_mode)); + // Push the qml mode flag + __ Push(Smi::FromInt(is_qml_mode())); @@ -1764,22 +1761,40 @@ index 97168cd..c45cdb6 100644 } -@@ -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. +@@ -2105,8 +2109,8 @@ void FullCodeGenerator::VisitCall(Call* expr) { + } else if (proxy != NULL && proxy->var()->IsUnallocated()) { + // Call to a global variable. Push global object as receiver for the + // call IC lookup. - __ push(GlobalObjectOperand()); -- EmitCallWithIC(expr, var->name(), RelocInfo::CODE_TARGET_CONTEXT); -+ __ push(var->is_qml_global() ? QmlGlobalObjectOperand() : GlobalObjectOperand()); -+ EmitCallWithIC(expr, var->name(), var->is_qml_global() ? RelocInfo::CODE_TARGET : RelocInfo::CODE_TARGET_CONTEXT); - } else if (var != NULL && var->AsSlot() != NULL && - var->AsSlot()->type() == Slot::LOOKUP) { +- EmitCallWithIC(expr, proxy->name(), RelocInfo::CODE_TARGET_CONTEXT); ++ __ push(proxy->var()->is_qml_global() ? QmlGlobalObjectOperand() : GlobalObjectOperand()); ++ EmitCallWithIC(expr, proxy->name(), proxy->var()->is_qml_global() ? RelocInfo::CODE_TARGET : RelocInfo::CODE_TARGET_CONTEXT); + } else if (proxy != NULL && proxy->var()->IsLookupSlot()) { // Call to a lookup slot (dynamically introduced variable). + Label slow, done; +@@ -3552,7 +3556,7 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) { + // but "delete this" is allowed. + ASSERT(strict_mode_flag() == kNonStrictMode || var->is_this()); + if (var->IsUnallocated()) { +- __ push(GlobalObjectOperand()); ++ __ push(var->is_qml_global() ? QmlGlobalObjectOperand() : GlobalObjectOperand()); + __ Push(var->name()); + __ Push(Smi::FromInt(kNonStrictMode)); + __ InvokeBuiltin(Builtins::DELETE, CALL_FUNCTION); +@@ -3850,7 +3854,7 @@ void FullCodeGenerator::VisitForTypeofValue(Expression* expr) { + if (proxy != NULL && proxy->var()->IsUnallocated()) { + Comment cmnt(masm_, "Global variable"); + __ Move(rcx, proxy->name()); +- __ movq(rax, GlobalObjectOperand()); ++ __ movq(rax, proxy->var()->is_qml_global() ? QmlGlobalObjectOperand() : GlobalObjectOperand()); + Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); + // Use a regular load, not a contextual load, to avoid a reference + // error. diff --git a/src/x64/lithium-codegen-x64.cc b/src/x64/lithium-codegen-x64.cc -index 202e7a2..45acbdf 100644 +index 45aaad7..08050f0 100644 --- a/src/x64/lithium-codegen-x64.cc +++ b/src/x64/lithium-codegen-x64.cc -@@ -174,12 +174,13 @@ bool LCodeGen::GeneratePrologue() { +@@ -196,12 +196,13 @@ bool LCodeGen::GeneratePrologue() { // Possibly allocate a local context. int heap_slots = scope()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; @@ -1794,8 +1809,8 @@ index 202e7a2..45acbdf 100644 + FastNewContextStub stub((heap_slots < 0)?0:heap_slots); __ CallStub(&stub); } else { - __ CallRuntime(Runtime::kNewContext, 1); -@@ -2540,7 +2541,7 @@ void LCodeGen::DoOuterContext(LOuterContext* instr) { + __ CallRuntime(Runtime::kNewFunctionContext, 1); +@@ -2581,7 +2582,7 @@ void LCodeGen::DoOuterContext(LOuterContext* instr) { void LCodeGen::DoGlobalObject(LGlobalObject* instr) { Register result = ToRegister(instr->result()); @@ -1805,10 +1820,10 @@ index 202e7a2..45acbdf 100644 diff --git a/src/x64/lithium-x64.cc b/src/x64/lithium-x64.cc -index 07ca3a5..00feeac 100644 +index a67a593..a243fef 100644 --- a/src/x64/lithium-x64.cc +++ b/src/x64/lithium-x64.cc -@@ -1194,7 +1194,7 @@ LInstruction* LChunkBuilder::DoOuterContext(HOuterContext* instr) { +@@ -1117,7 +1117,7 @@ LInstruction* LChunkBuilder::DoOuterContext(HOuterContext* instr) { LInstruction* LChunkBuilder::DoGlobalObject(HGlobalObject* instr) { @@ -1818,10 +1833,10 @@ index 07ca3a5..00feeac 100644 diff --git a/src/x64/lithium-x64.h b/src/x64/lithium-x64.h -index 15bb894..16f754c 100644 +index d43a86a..cf89181 100644 --- a/src/x64/lithium-x64.h +++ b/src/x64/lithium-x64.h -@@ -1365,7 +1365,13 @@ class LOuterContext: public LTemplateInstruction<1, 1, 0> { +@@ -1301,7 +1301,13 @@ class LOuterContext: public LTemplateInstruction<1, 1, 0> { class LGlobalObject: public LTemplateInstruction<1, 0, 0> { public: @@ -1836,10 +1851,10 @@ index 15bb894..16f754c 100644 diff --git a/src/x64/macro-assembler-x64.h b/src/x64/macro-assembler-x64.h -index 4c17720..aa284ed 100644 +index 7e0ba00..744ce20 100644 --- a/src/x64/macro-assembler-x64.h +++ b/src/x64/macro-assembler-x64.h -@@ -1233,6 +1233,11 @@ static inline Operand GlobalObjectOperand() { +@@ -1413,6 +1413,11 @@ static inline Operand GlobalObjectOperand() { } diff --git a/src/v8/0006-Allow-access-to-the-calling-script-data.patch b/src/v8/0005-Allow-access-to-the-calling-script-data.patch index 356142d654..a8cdc1dd54 100644 --- a/src/v8/0006-Allow-access-to-the-calling-script-data.patch +++ b/src/v8/0005-Allow-access-to-the-calling-script-data.patch @@ -1,7 +1,7 @@ -From 1209b88e96f253cdc19aa4c95e011c84597844f0 Mon Sep 17 00:00:00 2001 +From 2608243d70a8fcb0335f3520d5de1ac3cd854e87 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 06/16] Allow access to the calling script data +Date: Fri, 14 Oct 2011 17:03:06 +1000 +Subject: [PATCH 05/11] Allow access to the calling script data --- include/v8.h | 1 + @@ -9,10 +9,10 @@ Subject: [PATCH 06/16] 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 d78ab1f..2bc0ed1 100644 +index 193e2fe..c094d08 100644 --- a/include/v8.h +++ b/include/v8.h -@@ -3337,6 +3337,7 @@ class V8EXPORT Context { +@@ -3517,6 +3517,7 @@ class V8EXPORT Context { */ static Local<Context> GetCalling(); static Local<Object> GetCallingQmlGlobal(); @@ -21,10 +21,10 @@ index d78ab1f..2bc0ed1 100644 /** * Sets the security token for the context. To access an object in diff --git a/src/api.cc b/src/api.cc -index 39767f4..ff74efb 100644 +index fd718c8..526aa02 100644 --- a/src/api.cc +++ b/src/api.cc -@@ -3976,6 +3976,18 @@ v8::Local<v8::Object> Context::GetCallingQmlGlobal() { +@@ -4361,6 +4361,18 @@ v8::Local<v8::Object> Context::GetCallingQmlGlobal() { } } diff --git a/src/v8/0008-Add-custom-object-compare-callback.patch b/src/v8/0006-Add-custom-object-compare-callback.patch index 125668805e..f024009d41 100644 --- a/src/v8/0008-Add-custom-object-compare-callback.patch +++ b/src/v8/0006-Add-custom-object-compare-callback.patch @@ -1,7 +1,7 @@ -From a7c491e6e533110a17fe9f7d47cf92a1b2263180 Mon Sep 17 00:00:00 2001 +From 1c747846df3be9021aff2b0fc402cdd3a239e86b 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 08/16] Add custom object compare callback +Date: Wed, 25 May 2011 10:36:13 +1000 +Subject: [PATCH 06/11] Add custom object compare callback A global custom object comparison callback can be set with: V8::SetUserObjectComparisonCallbackFunction() @@ -14,24 +14,25 @@ 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/api.cc | 22 ++++++++++++++++++++++ + src/arm/code-stubs-arm.cc | 43 +++++++++++++++++++++++++++++++++++++++++-- src/factory.cc | 8 ++++++++ - src/ia32/code-stubs-ia32.cc | 40 ++++++++++++++++++++++++++++++++++++++++ + src/ia32/code-stubs-ia32.cc | 39 +++++++++++++++++++++++++++++++++++++++ + src/isolate.cc | 7 +++++++ src/isolate.h | 8 ++++++++ - src/objects-inl.h | 15 +++++++++++++++ - src/objects.h | 10 +++++++++- + src/objects-inl.h | 21 ++++++++++++++++++--- + src/objects.cc | 8 ++++---- + src/objects.h | 12 ++++++++++-- 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(-) + 13 files changed, 231 insertions(+), 11 deletions(-) diff --git a/include/v8.h b/include/v8.h -index 99f4b9a..7544deb 100644 +index c094d08..6baf2b2 100644 --- a/include/v8.h +++ b/include/v8.h -@@ -2366,6 +2366,12 @@ class V8EXPORT ObjectTemplate : public Template { +@@ -2501,6 +2501,12 @@ class V8EXPORT ObjectTemplate : public Template { bool HasExternalResource(); void SetHasExternalResource(bool value); @@ -44,18 +45,18 @@ index 99f4b9a..7544deb 100644 private: ObjectTemplate(); static Local<ObjectTemplate> New(Handle<FunctionTemplate> constructor); -@@ -2566,6 +2572,10 @@ typedef void (*FailedAccessCheckCallback)(Local<Object> target, +@@ -2720,6 +2726,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 --- ++// --- User Object Comparisoa nCallback --- +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 + // --- AllowCodeGenerationFromStrings callbacks --- /** -@@ -2816,6 +2826,9 @@ class V8EXPORT V8 { +@@ -3046,6 +3056,9 @@ class V8EXPORT V8 { /** Callback function for reporting failed access checks.*/ static void SetFailedAccessCheckCallbackFunction(FailedAccessCheckCallback); @@ -66,13 +67,13 @@ index 99f4b9a..7544deb 100644 * 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 ff74efb..2436031 100644 +index 526aa02..6f6297d 100644 --- a/src/api.cc +++ b/src/api.cc -@@ -1321,6 +1321,16 @@ void ObjectTemplate::SetHasExternalResource(bool value) - } +@@ -1464,6 +1464,17 @@ void ObjectTemplate::SetHasExternalResource(bool value) } + +void ObjectTemplate::MarkAsUseUserObjectComparison() +{ + i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); @@ -83,13 +84,15 @@ index ff74efb..2436031 100644 + EnsureConstructor(this); + Utils::OpenHandle(this)->set_use_user_object_comparison(i::Smi::FromInt(1)); +} - ++ // --- S c r i p t D a t a --- -@@ -4632,6 +4642,15 @@ void V8::SetFailedAccessCheckCallbackFunction( + +@@ -5106,6 +5117,17 @@ void V8::SetFailedAccessCheckCallbackFunction( isolate->SetFailedAccessCheckCallback(callback); } ++ +void V8::SetUserObjectComparisonCallbackFunction( + UserObjectComparisonCallback callback) { + i::Isolate* isolate = i::Isolate::Current(); @@ -99,14 +102,15 @@ index ff74efb..2436031 100644 + 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 +index 00ac676..a67b3a0 100644 --- a/src/arm/code-stubs-arm.cc +++ b/src/arm/code-stubs-arm.cc -@@ -1563,6 +1563,36 @@ void CompareStub::Generate(MacroAssembler* masm) { +@@ -1494,6 +1494,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. @@ -122,12 +126,12 @@ index a2626bf..749c9be 100644 + __ CompareObjectType(r1, r3, r4, JS_OBJECT_TYPE); + __ b(ne, ¬_user_equal); + -+ __ ldrb(r2, FieldMemOperand(r2, Map::kBitField3Offset)); ++ __ 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::kBitField3Offset)); ++ __ ldrb(r3, FieldMemOperand(r3, Map::kBitField2Offset)); + __ and_(r3, r3, Operand(1 << Map::kUseUserObjectComparison)); + __ cmp(r3, Operand(1 << Map::kUseUserObjectComparison)); + __ b(ne, ¬_user_equal); @@ -140,24 +144,25 @@ index a2626bf..749c9be 100644 + __ 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_); -@@ -5802,10 +5832,18 @@ void ICCompareStub::GenerateObjects(MacroAssembler* masm) { - __ tst(r2, Operand(kSmiTagMask)); - __ b(eq, &miss); +@@ -6544,10 +6575,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::kBitField3Offset)); ++ __ 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::kBitField3Offset)); ++ __ ldrb(r2, FieldMemOperand(r2, Map::kBitField2Offset)); + __ and_(r2, r2, Operand(1 << Map::kUseUserObjectComparison)); + __ cmp(r2, Operand(1 << Map::kUseUserObjectComparison)); + __ b(eq, &miss); @@ -165,10 +170,10 @@ index a2626bf..749c9be 100644 ASSERT(GetCondition() == eq); __ sub(r0, r0, Operand(r1)); diff --git a/src/factory.cc b/src/factory.cc -index d530a75..6f8c7de 100644 +index e3cccae..96d3458 100644 --- a/src/factory.cc +++ b/src/factory.cc -@@ -998,6 +998,7 @@ Handle<JSFunction> Factory::CreateApiFunction( +@@ -1120,6 +1120,7 @@ Handle<JSFunction> Factory::CreateApiFunction( int internal_field_count = 0; bool has_external_resource = false; @@ -176,7 +181,7 @@ index d530a75..6f8c7de 100644 if (!obj->instance_template()->IsUndefined()) { Handle<ObjectTemplateInfo> instance_template = -@@ -1007,6 +1008,8 @@ Handle<JSFunction> Factory::CreateApiFunction( +@@ -1129,6 +1130,8 @@ Handle<JSFunction> Factory::CreateApiFunction( Smi::cast(instance_template->internal_field_count())->value(); has_external_resource = !instance_template->has_external_resource()->IsUndefined(); @@ -185,7 +190,7 @@ index d530a75..6f8c7de 100644 } int instance_size = kPointerSize * internal_field_count; -@@ -1051,6 +1054,11 @@ Handle<JSFunction> Factory::CreateApiFunction( +@@ -1173,6 +1176,11 @@ Handle<JSFunction> Factory::CreateApiFunction( map->set_has_external_resource(true); } @@ -198,15 +203,15 @@ index d530a75..6f8c7de 100644 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 +index 6cc80d3..cabf78f 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."); - } +@@ -3931,6 +3931,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. + { -+ NearLabel not_user_equal, user_equal; ++ Label not_user_equal, user_equal; + __ test(eax, Immediate(kSmiTagMask)); + __ j(zero, ¬_user_equal); + __ test(edx, Immediate(kSmiTagMask)); @@ -218,10 +223,10 @@ index afa599e..0964ab9 100644 + __ CmpObjectType(edx, JS_OBJECT_TYPE, ecx); + __ j(not_equal, ¬_user_equal); + -+ __ test_b(FieldOperand(ebx, Map::kBitField3Offset), ++ __ test_b(FieldOperand(ebx, Map::kBitField2Offset), + 1 << Map::kUseUserObjectComparison); + __ j(not_zero, &user_equal); -+ __ test_b(FieldOperand(ecx, Map::kBitField3Offset), ++ __ test_b(FieldOperand(ecx, Map::kBitField2Offset), + 1 << Map::kUseUserObjectComparison); + __ j(not_zero, &user_equal); + @@ -238,40 +243,64 @@ index afa599e..0964ab9 100644 + __ bind(¬_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) { + // Identical objects can be compared fast, but there are some tricky cases + // for NaN and undefined. + { +@@ -6409,8 +6442,14 @@ void ICCompareStub::GenerateObjects(MacroAssembler* masm) { __ CmpObjectType(eax, JS_OBJECT_TYPE, ecx); - __ j(not_equal, &miss, not_taken); -+ __ test_b(FieldOperand(ecx, Map::kBitField3Offset), + __ j(not_equal, &miss, Label::kNear); ++ __ test_b(FieldOperand(ecx, Map::kBitField2Offset), + 1 << Map::kUseUserObjectComparison); -+ __ j(not_zero, &miss); ++ __ j(not_zero, &miss, Label::kNear); __ CmpObjectType(edx, JS_OBJECT_TYPE, ecx); - __ j(not_equal, &miss, not_taken); -+ __ test_b(FieldOperand(ecx, Map::kBitField3Offset), + __ j(not_equal, &miss, Label::kNear); ++ __ test_b(FieldOperand(ecx, Map::kBitField2Offset), + 1 << Map::kUseUserObjectComparison); -+ __ j(not_zero, &miss); ++ __ j(not_zero, &miss, Label::kNear); ASSERT(GetCondition() == equal); - __ sub(eax, Operand(edx)); + __ sub(eax, edx); +diff --git a/src/isolate.cc b/src/isolate.cc +index 951f428..6a86bf1 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; + } +@@ -717,6 +718,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 35ffcb4..8130397 100644 +index 01ab04e..06ef22d 100644 --- a/src/isolate.h +++ b/src/isolate.h -@@ -267,6 +267,9 @@ class ThreadLocalTop BASE_EMBEDDED { +@@ -255,6 +255,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(); + // Whether out of memory exceptions should be ignored. + bool ignore_out_of_memory_; -@@ -699,6 +702,11 @@ class Isolate { +@@ -701,6 +704,11 @@ class Isolate { void SetFailedAccessCheckCallback(v8::FailedAccessCheckCallback callback); void ReportFailedAccessCheck(JSObject* receiver, v8::AccessType type); @@ -284,63 +313,116 @@ index 35ffcb4..8130397 100644 // 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 +index 375df0f..4657482 100644 --- a/src/objects-inl.h +++ b/src/objects-inl.h -@@ -2552,6 +2552,19 @@ bool Map::has_external_resource() +@@ -2859,14 +2859,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; + } + + +@@ -2896,6 +2896,19 @@ bool Map::has_external_resource() } +void Map::set_use_user_object_comparison(bool value) { + if (value) { -+ set_bit_field3(bit_field3() | (1 << kUseUserObjectComparison)); ++ set_bit_field2(bit_field2() | (1 << kUseUserObjectComparison)); + } else { -+ set_bit_field3(bit_field3() & ~(1 << kUseUserObjectComparison)); ++ set_bit_field2(bit_field2() & ~(1 << kUseUserObjectComparison)); + } +} + +bool Map::use_user_object_comparison() { -+ return ((1 << kUseUserObjectComparison) & bit_field3()) != 0; ++ return ((1 << kUseUserObjectComparison) & bit_field2()) != 0; +} + + void Map::set_named_interceptor_is_fallback(bool value) { if (value) { -@@ -3050,6 +3063,8 @@ ACCESSORS(ObjectTemplateInfo, internal_field_count, Object, +@@ -3429,6 +3442,8 @@ ACCESSORS(ObjectTemplateInfo, internal_field_count, Object, kInternalFieldCountOffset) - ACCESSORS(ObjectTemplateInfo, has_external_resource, Object, + 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 8e1773f..28e6d79 100644 +--- a/src/objects.cc ++++ b/src/objects.cc +@@ -7159,8 +7159,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 +@@ -7180,8 +7180,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 edbc47a..e75e9f1 100644 +index 71895be..881c24e 100644 --- a/src/objects.h +++ b/src/objects.h -@@ -3724,6 +3724,11 @@ class Map: public HeapObject { +@@ -4084,6 +4084,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; ++ + // [prototype]: implicit prototype object. + DECL_ACCESSORS(prototype, Object) + +@@ -4303,7 +4308,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; +@@ -4322,6 +4327,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; -@@ -6442,6 +6448,7 @@ class ObjectTemplateInfo: public TemplateInfo { +@@ -7306,6 +7312,7 @@ class ObjectTemplateInfo: public TemplateInfo { DECL_ACCESSORS(constructor, Object) DECL_ACCESSORS(internal_field_count, Object) DECL_ACCESSORS(has_external_resource, Object) @@ -348,7 +430,7 @@ index edbc47a..e75e9f1 100644 static inline ObjectTemplateInfo* cast(Object* obj); -@@ -6459,7 +6466,8 @@ class ObjectTemplateInfo: public TemplateInfo { +@@ -7323,7 +7330,8 @@ class ObjectTemplateInfo: public TemplateInfo { static const int kInternalFieldCountOffset = kConstructorOffset + kPointerSize; static const int kHasExternalResourceOffset = kInternalFieldCountOffset + kPointerSize; @@ -359,10 +441,10 @@ index edbc47a..e75e9f1 100644 diff --git a/src/runtime.cc b/src/runtime.cc -index c13f92d..b50de80 100644 +index 0388a77..24b3de0 100644 --- a/src/runtime.cc +++ b/src/runtime.cc -@@ -6279,6 +6279,29 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_StringEquals) { +@@ -7008,6 +7008,29 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_StringEquals) { } @@ -393,10 +475,10 @@ index c13f92d..b50de80 100644 NoHandleAllocation ha; ASSERT(args.length() == 3); diff --git a/src/runtime.h b/src/runtime.h -index 5e97173..0d754f9 100644 +index 284f723..5d6bf5e 100644 --- a/src/runtime.h +++ b/src/runtime.h -@@ -146,6 +146,7 @@ namespace internal { +@@ -157,6 +157,7 @@ namespace internal { /* Comparisons */ \ F(NumberEquals, 2, 1) \ F(StringEquals, 2, 1) \ @@ -404,39 +486,16 @@ index 5e97173..0d754f9 100644 \ 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 +index 6ab12fc..3be2c4b 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); - } +@@ -3005,6 +3005,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. + { -+ NearLabel not_user_equal, user_equal; ++ Label not_user_equal, user_equal; + __ JumpIfSmi(rax, ¬_user_equal); + __ JumpIfSmi(rdx, ¬_user_equal); + @@ -446,10 +505,10 @@ index d923494..10b9b56 100644 + __ CmpObjectType(rdx, JS_OBJECT_TYPE, rcx); + __ j(not_equal, ¬_user_equal); + -+ __ testb(FieldOperand(rbx, Map::kBitField3Offset), ++ __ testb(FieldOperand(rbx, Map::kBitField2Offset), + Immediate(1 << Map::kUseUserObjectComparison)); + __ j(not_zero, &user_equal); -+ __ testb(FieldOperand(rcx, Map::kBitField3Offset), ++ __ testb(FieldOperand(rcx, Map::kBitField2Offset), + Immediate(1 << Map::kUseUserObjectComparison)); + __ j(not_zero, &user_equal); + @@ -466,21 +525,21 @@ index d923494..10b9b56 100644 + __ bind(¬_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) { + // Two identical objects are equal unless they are both NaN or undefined. + { + Label not_identical; +@@ -5337,8 +5368,14 @@ void ICCompareStub::GenerateObjects(MacroAssembler* masm) { __ CmpObjectType(rax, JS_OBJECT_TYPE, rcx); - __ j(not_equal, &miss, not_taken); -+ __ testb(FieldOperand(rcx, Map::kBitField3Offset), + __ j(not_equal, &miss, Label::kNear); ++ __ testb(FieldOperand(rcx, Map::kBitField2Offset), + Immediate(1 << Map::kUseUserObjectComparison)); -+ __ j(not_zero, &miss); ++ __ j(not_zero, &miss, Label::kNear); __ CmpObjectType(rdx, JS_OBJECT_TYPE, rcx); - __ j(not_equal, &miss, not_taken); -+ __ testb(FieldOperand(rcx, Map::kBitField3Offset), + __ j(not_equal, &miss, Label::kNear); ++ __ testb(FieldOperand(rcx, Map::kBitField2Offset), + Immediate(1 << Map::kUseUserObjectComparison)); -+ __ j(not_zero, &miss); ++ __ j(not_zero, &miss, Label::kNear); ASSERT(GetCondition() == equal); __ subq(rax, rdx); diff --git a/src/v8/0015-Allow-a-script-to-be-flagged-as-native.patch b/src/v8/0007-Allow-a-script-to-be-flagged-as-native.patch index d66e370217..396d1f7add 100644 --- a/src/v8/0015-Allow-a-script-to-be-flagged-as-native.patch +++ b/src/v8/0007-Allow-a-script-to-be-flagged-as-native.patch @@ -1,7 +1,7 @@ -From 523f03f03b1ac16d272a13389f8a5654d9ff12e6 Mon Sep 17 00:00:00 2001 +From a1572a979803dda787be4a7095d5c37e926443a7 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 15/16] Allow a script to be flagged as "native" +Subject: [PATCH 07/11] 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 @@ -13,10 +13,10 @@ still have it appear sensibly to the user. 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/include/v8.h b/include/v8.h -index 5e1ce50..a2d61d1 100644 +index 6baf2b2..229ddbd 100644 --- a/include/v8.h +++ b/include/v8.h -@@ -578,8 +578,9 @@ class ScriptOrigin { +@@ -588,8 +588,9 @@ class ScriptOrigin { class V8EXPORT Script { public: enum CompileFlags { @@ -29,10 +29,10 @@ index 5e1ce50..a2d61d1 100644 /** diff --git a/src/compiler.cc b/src/compiler.cc -index d2191b9..873018c 100755 +index 596df4a..b760b71 100644 --- a/src/compiler.cc +++ b/src/compiler.cc -@@ -507,7 +507,7 @@ Handle<SharedFunctionInfo> Compiler::Compile(Handle<String> source, +@@ -501,7 +501,7 @@ Handle<SharedFunctionInfo> Compiler::Compile(Handle<String> source, // Create a script object describing the script to be compiled. Handle<Script> script = FACTORY->NewScript(source); diff --git a/src/v8/0011-QtScript-V8-Add-new-v8-api-to-check-if-a-value-is-an.patch b/src/v8/0008-QtScript-V8-Add-new-v8-api-to-check-if-a-value-is-an.patch index 7cbc2d474b..007f14a821 100644 --- a/src/v8/0011-QtScript-V8-Add-new-v8-api-to-check-if-a-value-is-an.patch +++ b/src/v8/0008-QtScript-V8-Add-new-v8-api-to-check-if-a-value-is-an.patch @@ -1,7 +1,7 @@ -From 5f3e5dd6901b54707ea4f868d8fa7317c4ab3852 Mon Sep 17 00:00:00 2001 +From 3c304e3712ebf9f0df0b544032f0f83945d08028 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 11/16] QtScript/V8: Add new v8 api to check if a value is an +Subject: [PATCH 08/11] QtScript/V8: Add new v8 api to check if a value is an error. New function v8::Value::IsError was created. @@ -15,10 +15,10 @@ research. 3 files changed, 12 insertions(+), 0 deletions(-) diff --git a/include/v8.h b/include/v8.h -index 18527e1..43e00f5 100644 +index 229ddbd..d995e54 100644 --- a/include/v8.h +++ b/include/v8.h -@@ -937,6 +937,11 @@ class Value : public Data { +@@ -967,6 +967,11 @@ class Value : public Data { */ V8EXPORT bool IsRegExp() const; @@ -31,10 +31,10 @@ index 18527e1..43e00f5 100644 V8EXPORT Local<Number> ToNumber() const; V8EXPORT Local<String> ToString() const; diff --git a/src/api.cc b/src/api.cc -index 1a585d6..bd435eb 100644 +index 6f6297d..c21af67 100644 --- a/src/api.cc +++ b/src/api.cc -@@ -2108,6 +2108,12 @@ bool Value::IsRegExp() const { +@@ -2316,6 +2316,12 @@ bool Value::IsRegExp() const { return obj->IsJSRegExp(); } @@ -48,10 +48,10 @@ index 1a585d6..bd435eb 100644 Local<String> Value::ToString() const { i::Handle<i::Object> obj = Utils::OpenHandle(this); diff --git a/src/heap.h b/src/heap.h -index 8cbf378..db90bb9 100644 +index bab4c63..ad83b70 100644 --- a/src/heap.h +++ b/src/heap.h -@@ -169,6 +169,7 @@ inline Heap* _inline_get_heap_(); +@@ -188,6 +188,7 @@ inline Heap* _inline_get_heap_(); V(string_symbol, "string") \ V(String_symbol, "String") \ V(Date_symbol, "Date") \ diff --git a/src/v8/0009-Add-CallAsFunction-method-to-the-Object-class-in-the.patch b/src/v8/0009-Add-CallAsFunction-method-to-the-Object-class-in-the.patch deleted file mode 100644 index b89f152a04..0000000000 --- a/src/v8/0009-Add-CallAsFunction-method-to-the-Object-class-in-the.patch +++ /dev/null @@ -1,287 +0,0 @@ -From 15ce2909579aef8c8f6b0c2c07fdebbaf0f4d611 Mon Sep 17 00:00:00 2001 -From: ager@chromium.org <ager@chromium.org> -Date: Wed, 4 May 2011 13:03:08 +0000 -Subject: [PATCH 09/16] Add CallAsFunction method to the Object class in the - API - -Patch by Peter Varga. - -BUG=v8:1336 -TEST=cctest/test-api/CallAsFunction - -Review URL: http://codereview.chromium.org/6883045 - -git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@7781 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 ---- - include/v8.h | 8 +++ - src/api.cc | 31 +++++++++++ - src/execution.cc | 24 ++++++++ - src/execution.h | 2 + - test/cctest/test-api.cc | 135 ++++++++++++++++++++++++++++++++++------------- - 5 files changed, 163 insertions(+), 37 deletions(-) - -diff --git a/include/v8.h b/include/v8.h -index 7544deb..277153e 100644 ---- a/include/v8.h -+++ b/include/v8.h -@@ -1758,6 +1758,14 @@ class Object : public Value { - V8EXPORT ExternalArrayType GetIndexedPropertiesExternalArrayDataType(); - V8EXPORT int GetIndexedPropertiesExternalArrayDataLength(); - -+ /** -+ * Call an Object as a function if a callback is set by the -+ * ObjectTemplate::SetCallAsFunctionHandler method. -+ */ -+ V8EXPORT Local<Value> CallAsFunction(Handle<Object> recv, -+ int argc, -+ Handle<Value> argv[]); -+ - V8EXPORT static Local<Object> New(); - static inline Object* Cast(Value* obj); - private: -diff --git a/src/api.cc b/src/api.cc -index 2436031..e412e51 100644 ---- a/src/api.cc -+++ b/src/api.cc -@@ -3259,6 +3259,37 @@ int v8::Object::GetIndexedPropertiesExternalArrayDataLength() { - } - - -+Local<v8::Value> Object::CallAsFunction(v8::Handle<v8::Object> recv, int argc, -+ v8::Handle<v8::Value> argv[]) { -+ i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); -+ ON_BAILOUT(isolate, "v8::Object::CallAsFunction()", -+ return Local<v8::Value>()); -+ LOG_API(isolate, "Object::CallAsFunction"); -+ ENTER_V8(isolate); -+ HandleScope scope; -+ i::Handle<i::JSObject> obj = Utils::OpenHandle(this); -+ i::Handle<i::Object> recv_obj = Utils::OpenHandle(*recv); -+ STATIC_ASSERT(sizeof(v8::Handle<v8::Value>) == sizeof(i::Object**)); -+ i::Object*** args = reinterpret_cast<i::Object***>(argv); -+ i::Handle<i::JSFunction> fun = i::Handle<i::JSFunction>(); -+ if (obj->IsJSFunction()) { -+ fun = i::Handle<i::JSFunction>::cast(obj); -+ } else { -+ EXCEPTION_PREAMBLE(isolate); -+ i::Handle<i::Object> delegate = -+ i::Execution::TryGetFunctionDelegate(obj, &has_pending_exception); -+ EXCEPTION_BAILOUT_CHECK(isolate, Local<Value>()); -+ fun = i::Handle<i::JSFunction>::cast(delegate); -+ recv_obj = obj; -+ } -+ EXCEPTION_PREAMBLE(isolate); -+ i::Handle<i::Object> returned = -+ i::Execution::Call(fun, recv_obj, argc, args, &has_pending_exception); -+ EXCEPTION_BAILOUT_CHECK(isolate, Local<Value>()); -+ return scope.Close(Utils::ToLocal(returned)); -+} -+ -+ - Local<v8::Object> Function::NewInstance() const { - return NewInstance(0, NULL); - } -diff --git a/src/execution.cc b/src/execution.cc -index 1632076..894d741 100644 ---- a/src/execution.cc -+++ b/src/execution.cc -@@ -254,6 +254,30 @@ Handle<Object> Execution::GetFunctionDelegate(Handle<Object> object) { - } - - -+Handle<Object> Execution::TryGetFunctionDelegate(Handle<Object> object, -+ bool* has_pending_exception) { -+ ASSERT(!object->IsJSFunction()); -+ Isolate* isolate = Isolate::Current(); -+ -+ // Objects created through the API can have an instance-call handler -+ // that should be used when calling the object as a function. -+ if (object->IsHeapObject() && -+ HeapObject::cast(*object)->map()->has_instance_call_handler()) { -+ return Handle<JSFunction>( -+ isolate->global_context()->call_as_function_delegate()); -+ } -+ -+ // If the Object doesn't have an instance-call handler we should -+ // throw a non-callable exception. -+ i::Handle<i::Object> error_obj = isolate->factory()->NewTypeError( -+ "called_non_callable", i::HandleVector<i::Object>(&object, 1)); -+ isolate->Throw(*error_obj); -+ *has_pending_exception = true; -+ -+ return isolate->factory()->undefined_value(); -+} -+ -+ - Handle<Object> Execution::GetConstructorDelegate(Handle<Object> object) { - ASSERT(!object->IsJSFunction()); - Isolate* isolate = Isolate::Current(); -diff --git a/src/execution.h b/src/execution.h -index a476eb4..0a0be51 100644 ---- a/src/execution.h -+++ b/src/execution.h -@@ -144,6 +144,8 @@ class Execution : public AllStatic { - // Get a function delegate (or undefined) for the given non-function - // object. Used for support calling objects as functions. - static Handle<Object> GetFunctionDelegate(Handle<Object> object); -+ static Handle<Object> TryGetFunctionDelegate(Handle<Object> object, -+ bool* has_pending_exception); - - // Get a function delegate (or undefined) for the given non-function - // object. Used for support calling objects as constructors. -diff --git a/test/cctest/test-api.cc b/test/cctest/test-api.cc -index d7621d1..693d51e 100644 ---- a/test/cctest/test-api.cc -+++ b/test/cctest/test-api.cc -@@ -6962,50 +6962,111 @@ THREADED_TEST(CallAsFunction) { - v8::HandleScope scope; - LocalContext context; - -- Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(); -- Local<ObjectTemplate> instance_template = t->InstanceTemplate(); -- instance_template->SetCallAsFunctionHandler(call_as_function); -- Local<v8::Object> instance = t->GetFunction()->NewInstance(); -- context->Global()->Set(v8_str("obj"), instance); -- v8::TryCatch try_catch; -- Local<Value> value; -- CHECK(!try_catch.HasCaught()); -+ { Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(); -+ Local<ObjectTemplate> instance_template = t->InstanceTemplate(); -+ instance_template->SetCallAsFunctionHandler(call_as_function); -+ Local<v8::Object> instance = t->GetFunction()->NewInstance(); -+ context->Global()->Set(v8_str("obj"), instance); -+ v8::TryCatch try_catch; -+ Local<Value> value; -+ CHECK(!try_catch.HasCaught()); - -- value = CompileRun("obj(42)"); -- CHECK(!try_catch.HasCaught()); -- CHECK_EQ(42, value->Int32Value()); -+ value = CompileRun("obj(42)"); -+ CHECK(!try_catch.HasCaught()); -+ CHECK_EQ(42, value->Int32Value()); - -- value = CompileRun("(function(o){return o(49)})(obj)"); -- CHECK(!try_catch.HasCaught()); -- CHECK_EQ(49, value->Int32Value()); -+ value = CompileRun("(function(o){return o(49)})(obj)"); -+ CHECK(!try_catch.HasCaught()); -+ CHECK_EQ(49, value->Int32Value()); - -- // test special case of call as function -- value = CompileRun("[obj]['0'](45)"); -- CHECK(!try_catch.HasCaught()); -- CHECK_EQ(45, value->Int32Value()); -+ // test special case of call as function -+ value = CompileRun("[obj]['0'](45)"); -+ CHECK(!try_catch.HasCaught()); -+ CHECK_EQ(45, value->Int32Value()); - -- value = CompileRun("obj.call = Function.prototype.call;" -- "obj.call(null, 87)"); -- CHECK(!try_catch.HasCaught()); -- CHECK_EQ(87, value->Int32Value()); -+ value = CompileRun("obj.call = Function.prototype.call;" -+ "obj.call(null, 87)"); -+ CHECK(!try_catch.HasCaught()); -+ CHECK_EQ(87, value->Int32Value()); - -- // Regression tests for bug #1116356: Calling call through call/apply -- // must work for non-function receivers. -- const char* apply_99 = "Function.prototype.call.apply(obj, [this, 99])"; -- value = CompileRun(apply_99); -- CHECK(!try_catch.HasCaught()); -- CHECK_EQ(99, value->Int32Value()); -+ // Regression tests for bug #1116356: Calling call through call/apply -+ // must work for non-function receivers. -+ const char* apply_99 = "Function.prototype.call.apply(obj, [this, 99])"; -+ value = CompileRun(apply_99); -+ CHECK(!try_catch.HasCaught()); -+ CHECK_EQ(99, value->Int32Value()); - -- const char* call_17 = "Function.prototype.call.call(obj, this, 17)"; -- value = CompileRun(call_17); -- CHECK(!try_catch.HasCaught()); -- CHECK_EQ(17, value->Int32Value()); -+ const char* call_17 = "Function.prototype.call.call(obj, this, 17)"; -+ value = CompileRun(call_17); -+ CHECK(!try_catch.HasCaught()); -+ CHECK_EQ(17, value->Int32Value()); - -- // Check that the call-as-function handler can be called through -- // new. -- value = CompileRun("new obj(43)"); -- CHECK(!try_catch.HasCaught()); -- CHECK_EQ(-43, value->Int32Value()); -+ // Check that the call-as-function handler can be called through -+ // new. -+ value = CompileRun("new obj(43)"); -+ CHECK(!try_catch.HasCaught()); -+ CHECK_EQ(-43, value->Int32Value()); -+ -+ // Check that the call-as-function handler can be called through -+ // the API. -+ v8::Handle<Value> args[] = { v8_num(28) }; -+ value = instance->CallAsFunction(instance, 1, args); -+ CHECK(!try_catch.HasCaught()); -+ CHECK_EQ(28, value->Int32Value()); -+ } -+ -+ { Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(); -+ Local<ObjectTemplate> instance_template = t->InstanceTemplate(); -+ Local<v8::Object> instance = t->GetFunction()->NewInstance(); -+ context->Global()->Set(v8_str("obj2"), instance); -+ v8::TryCatch try_catch; -+ Local<Value> value; -+ CHECK(!try_catch.HasCaught()); -+ -+ // Call an object without call-as-function handler through the JS -+ value = CompileRun("obj2(28)"); -+ CHECK(value.IsEmpty()); -+ CHECK(try_catch.HasCaught()); -+ String::AsciiValue exception_value1(try_catch.Exception()); -+ CHECK_EQ(*exception_value1, -+ "TypeError: Property 'obj2' of object " -+ "#<Object> is not a function"); -+ try_catch.Reset(); -+ -+ // Call an object without call-as-function handler through the API -+ value = CompileRun("obj2(28)"); -+ v8::Handle<Value> args[] = { v8_num(28) }; -+ value = instance->CallAsFunction(instance, 1, args); -+ CHECK(value.IsEmpty()); -+ CHECK(try_catch.HasCaught()); -+ String::AsciiValue exception_value2(try_catch.Exception()); -+ CHECK_EQ(*exception_value2, "TypeError: [object Object] is not a function"); -+ try_catch.Reset(); -+ } -+ -+ { Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(); -+ Local<ObjectTemplate> instance_template = t->InstanceTemplate(); -+ instance_template->SetCallAsFunctionHandler(ThrowValue); -+ Local<v8::Object> instance = t->GetFunction()->NewInstance(); -+ context->Global()->Set(v8_str("obj3"), instance); -+ v8::TryCatch try_catch; -+ Local<Value> value; -+ CHECK(!try_catch.HasCaught()); -+ -+ // Catch the exception which is thrown by call-as-function handler -+ value = CompileRun("obj3(22)"); -+ CHECK(try_catch.HasCaught()); -+ String::AsciiValue exception_value1(try_catch.Exception()); -+ CHECK_EQ(*exception_value1, "22"); -+ try_catch.Reset(); -+ -+ v8::Handle<Value> args[] = { v8_num(23) }; -+ value = instance->CallAsFunction(instance, 1, args); -+ CHECK(try_catch.HasCaught()); -+ String::AsciiValue exception_value2(try_catch.Exception()); -+ CHECK_EQ(*exception_value2, "23"); -+ try_catch.Reset(); -+ } - } - - --- -1.7.4.4 - diff --git a/src/v8/0014-Fix-deprecated-Python-code.patch b/src/v8/0009-Fix-deprecated-Python-code.patch index 9745a5c129..a5d2d084fb 100644 --- a/src/v8/0014-Fix-deprecated-Python-code.patch +++ b/src/v8/0009-Fix-deprecated-Python-code.patch @@ -1,7 +1,7 @@ -From ed5cc903d70f73780e5985e7d2de33f6b8d86402 Mon Sep 17 00:00:00 2001 +From 234a7bf490c4870f2d015221bb5158de4933519c 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 14/16] Fix deprecated Python code +Subject: [PATCH 09/11] Fix deprecated Python code Needed to make the scripts run on Python 3, which is the default python interpreter on some newer distros. @@ -13,10 +13,10 @@ Patch from http://code.google.com/p/v8/issues/detail?id=1391 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/js2c.py b/tools/js2c.py -index 2da132f..d13d53d 100755 +index a2ea8ea..fe6a72e 100644 --- a/tools/js2c.py +++ b/tools/js2c.py -@@ -187,14 +187,14 @@ def ReadMacros(lines): +@@ -194,14 +194,14 @@ def ReadMacros(lines): macro_match = MACRO_PATTERN.match(line) if macro_match: name = macro_match.group(1) diff --git a/src/v8/0010-Implement-CallAsConstructor-method-for-Object-in-the.patch b/src/v8/0010-Implement-CallAsConstructor-method-for-Object-in-the.patch deleted file mode 100644 index 847cb8657e..0000000000 --- a/src/v8/0010-Implement-CallAsConstructor-method-for-Object-in-the.patch +++ /dev/null @@ -1,398 +0,0 @@ -From 3ba270e3b93d292dc53a675a21479bdb0b50bbbe Mon Sep 17 00:00:00 2001 -From: ager@chromium.org <ager@chromium.org> -Date: Fri, 6 May 2011 11:07:52 +0000 -Subject: [PATCH 10/16] Implement CallAsConstructor method for Object in the - API - -Patch by Peter Varga. - -BUG=v8:1348 -TEST=cctest/test-api/ConstructorForObject - -Review URL: http://codereview.chromium.org/6902108 - -git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@7803 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 ---- - include/v8.h | 8 ++ - src/api.cc | 41 +++++++++- - src/execution.cc | 28 +++++++ - src/execution.h | 2 + - test/cctest/test-api.cc | 205 +++++++++++++++++++++++++++++++++++++++++++++-- - 5 files changed, 276 insertions(+), 8 deletions(-) - -diff --git a/include/v8.h b/include/v8.h -index 277153e..18527e1 100644 ---- a/include/v8.h -+++ b/include/v8.h -@@ -1766,6 +1766,14 @@ class Object : public Value { - int argc, - Handle<Value> argv[]); - -+ /** -+ * Call an Object as a consturctor if a callback is set by the -+ * ObjectTemplate::SetCallAsFunctionHandler method. -+ * Note: This method behaves like the Function::NewInstance method. -+ */ -+ V8EXPORT Local<Value> CallAsConstructor(int argc, -+ Handle<Value> argv[]); -+ - V8EXPORT static Local<Object> New(); - static inline Object* Cast(Value* obj); - private: -diff --git a/src/api.cc b/src/api.cc -index e412e51..1a585d6 100644 ---- a/src/api.cc -+++ b/src/api.cc -@@ -3266,7 +3266,7 @@ Local<v8::Value> Object::CallAsFunction(v8::Handle<v8::Object> recv, int argc, - return Local<v8::Value>()); - LOG_API(isolate, "Object::CallAsFunction"); - ENTER_V8(isolate); -- HandleScope scope; -+ i::HandleScope scope(isolate); - i::Handle<i::JSObject> obj = Utils::OpenHandle(this); - i::Handle<i::Object> recv_obj = Utils::OpenHandle(*recv); - STATIC_ASSERT(sizeof(v8::Handle<v8::Value>) == sizeof(i::Object**)); -@@ -3286,7 +3286,44 @@ Local<v8::Value> Object::CallAsFunction(v8::Handle<v8::Object> recv, int argc, - i::Handle<i::Object> returned = - i::Execution::Call(fun, recv_obj, argc, args, &has_pending_exception); - EXCEPTION_BAILOUT_CHECK(isolate, Local<Value>()); -- return scope.Close(Utils::ToLocal(returned)); -+ return Utils::ToLocal(scope.CloseAndEscape(returned)); -+} -+ -+ -+Local<v8::Value> Object::CallAsConstructor(int argc, -+ v8::Handle<v8::Value> argv[]) { -+ i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); -+ ON_BAILOUT(isolate, "v8::Object::CallAsConstructor()", -+ return Local<v8::Object>()); -+ LOG_API(isolate, "Object::CallAsConstructor"); -+ ENTER_V8(isolate); -+ i::HandleScope scope(isolate); -+ i::Handle<i::JSObject> obj = Utils::OpenHandle(this); -+ STATIC_ASSERT(sizeof(v8::Handle<v8::Value>) == sizeof(i::Object**)); -+ i::Object*** args = reinterpret_cast<i::Object***>(argv); -+ if (obj->IsJSFunction()) { -+ i::Handle<i::JSFunction> fun = i::Handle<i::JSFunction>::cast(obj); -+ EXCEPTION_PREAMBLE(isolate); -+ i::Handle<i::Object> returned = -+ i::Execution::New(fun, argc, args, &has_pending_exception); -+ EXCEPTION_BAILOUT_CHECK(isolate, Local<v8::Object>()); -+ return Utils::ToLocal(scope.CloseAndEscape( -+ i::Handle<i::JSObject>::cast(returned))); -+ } -+ EXCEPTION_PREAMBLE(isolate); -+ i::Handle<i::Object> delegate = -+ i::Execution::TryGetConstructorDelegate(obj, &has_pending_exception); -+ EXCEPTION_BAILOUT_CHECK(isolate, Local<v8::Object>()); -+ if (!delegate->IsUndefined()) { -+ i::Handle<i::JSFunction> fun = i::Handle<i::JSFunction>::cast(delegate); -+ EXCEPTION_PREAMBLE(isolate); -+ i::Handle<i::Object> returned = -+ i::Execution::Call(fun, obj, argc, args, &has_pending_exception); -+ EXCEPTION_BAILOUT_CHECK(isolate, Local<v8::Object>()); -+ ASSERT(!delegate->IsUndefined()); -+ return Utils::ToLocal(scope.CloseAndEscape(returned)); -+ } -+ return Local<v8::Object>(); - } - - -diff --git a/src/execution.cc b/src/execution.cc -index 894d741..afb352c 100644 ---- a/src/execution.cc -+++ b/src/execution.cc -@@ -297,6 +297,34 @@ Handle<Object> Execution::GetConstructorDelegate(Handle<Object> object) { - } - - -+Handle<Object> Execution::TryGetConstructorDelegate( -+ Handle<Object> object, -+ bool* has_pending_exception) { -+ ASSERT(!object->IsJSFunction()); -+ Isolate* isolate = Isolate::Current(); -+ -+ // If you return a function from here, it will be called when an -+ // attempt is made to call the given object as a constructor. -+ -+ // Objects created through the API can have an instance-call handler -+ // that should be used when calling the object as a function. -+ if (object->IsHeapObject() && -+ HeapObject::cast(*object)->map()->has_instance_call_handler()) { -+ return Handle<JSFunction>( -+ isolate->global_context()->call_as_constructor_delegate()); -+ } -+ -+ // If the Object doesn't have an instance-call handler we should -+ // throw a non-callable exception. -+ i::Handle<i::Object> error_obj = isolate->factory()->NewTypeError( -+ "called_non_callable", i::HandleVector<i::Object>(&object, 1)); -+ isolate->Throw(*error_obj); -+ *has_pending_exception = true; -+ -+ return isolate->factory()->undefined_value(); -+} -+ -+ - bool StackGuard::IsStackOverflow() { - ExecutionAccess access(isolate_); - return (thread_local_.jslimit_ != kInterruptLimit && -diff --git a/src/execution.h b/src/execution.h -index 0a0be51..ec2a195 100644 ---- a/src/execution.h -+++ b/src/execution.h -@@ -150,6 +150,8 @@ class Execution : public AllStatic { - // Get a function delegate (or undefined) for the given non-function - // object. Used for support calling objects as constructors. - static Handle<Object> GetConstructorDelegate(Handle<Object> object); -+ static Handle<Object> TryGetConstructorDelegate(Handle<Object> object, -+ bool* has_pending_exception); - }; - - -diff --git a/test/cctest/test-api.cc b/test/cctest/test-api.cc -index 693d51e..1334f63 100644 ---- a/test/cctest/test-api.cc -+++ b/test/cctest/test-api.cc -@@ -6746,6 +6746,200 @@ THREADED_TEST(Constructor) { - CHECK(value->BooleanValue()); - } - -+ -+static Handle<Value> ConstructorCallback(const Arguments& args) { -+ ApiTestFuzzer::Fuzz(); -+ Local<Object> This; -+ -+ if (args.IsConstructCall()) { -+ Local<Object> Holder = args.Holder(); -+ This = Object::New(); -+ Local<Value> proto = Holder->GetPrototype(); -+ if (proto->IsObject()) { -+ This->SetPrototype(proto); -+ } -+ } else { -+ This = args.This(); -+ } -+ -+ This->Set(v8_str("a"), args[0]); -+ return This; -+} -+ -+ -+static Handle<Value> FakeConstructorCallback(const Arguments& args) { -+ ApiTestFuzzer::Fuzz(); -+ return args[0]; -+} -+ -+ -+THREADED_TEST(ConstructorForObject) { -+ v8::HandleScope handle_scope; -+ LocalContext context; -+ -+ { Local<ObjectTemplate> instance_template = ObjectTemplate::New(); -+ instance_template->SetCallAsFunctionHandler(ConstructorCallback); -+ Local<Object> instance = instance_template->NewInstance(); -+ context->Global()->Set(v8_str("obj"), instance); -+ v8::TryCatch try_catch; -+ Local<Value> value; -+ CHECK(!try_catch.HasCaught()); -+ -+ // Call the Object's constructor with a 32-bit signed integer. -+ value = CompileRun("(function() { var o = new obj(28); return o.a; })()"); -+ CHECK(!try_catch.HasCaught()); -+ CHECK(value->IsInt32()); -+ CHECK_EQ(28, value->Int32Value()); -+ -+ Local<Value> args1[] = { v8_num(28) }; -+ Local<Value> value_obj1 = instance->CallAsConstructor(1, args1); -+ CHECK(value_obj1->IsObject()); -+ Local<Object> object1 = Local<Object>::Cast(value_obj1); -+ value = object1->Get(v8_str("a")); -+ CHECK(value->IsInt32()); -+ CHECK(!try_catch.HasCaught()); -+ CHECK_EQ(28, value->Int32Value()); -+ -+ // Call the Object's constructor with a String. -+ value = CompileRun( -+ "(function() { var o = new obj('tipli'); return o.a; })()"); -+ CHECK(!try_catch.HasCaught()); -+ CHECK(value->IsString()); -+ String::AsciiValue string_value1(value->ToString()); -+ CHECK_EQ("tipli", *string_value1); -+ -+ Local<Value> args2[] = { v8_str("tipli") }; -+ Local<Value> value_obj2 = instance->CallAsConstructor(1, args2); -+ CHECK(value_obj2->IsObject()); -+ Local<Object> object2 = Local<Object>::Cast(value_obj2); -+ value = object2->Get(v8_str("a")); -+ CHECK(!try_catch.HasCaught()); -+ CHECK(value->IsString()); -+ String::AsciiValue string_value2(value->ToString()); -+ CHECK_EQ("tipli", *string_value2); -+ -+ // Call the Object's constructor with a Boolean. -+ value = CompileRun("(function() { var o = new obj(true); return o.a; })()"); -+ CHECK(!try_catch.HasCaught()); -+ CHECK(value->IsBoolean()); -+ CHECK_EQ(true, value->BooleanValue()); -+ -+ Handle<Value> args3[] = { v8::Boolean::New(true) }; -+ Local<Value> value_obj3 = instance->CallAsConstructor(1, args3); -+ CHECK(value_obj3->IsObject()); -+ Local<Object> object3 = Local<Object>::Cast(value_obj3); -+ value = object3->Get(v8_str("a")); -+ CHECK(!try_catch.HasCaught()); -+ CHECK(value->IsBoolean()); -+ CHECK_EQ(true, value->BooleanValue()); -+ -+ // Call the Object's constructor with undefined. -+ Handle<Value> args4[] = { v8::Undefined() }; -+ Local<Value> value_obj4 = instance->CallAsConstructor(1, args4); -+ CHECK(value_obj4->IsObject()); -+ Local<Object> object4 = Local<Object>::Cast(value_obj4); -+ value = object4->Get(v8_str("a")); -+ CHECK(!try_catch.HasCaught()); -+ CHECK(value->IsUndefined()); -+ -+ // Call the Object's constructor with null. -+ Handle<Value> args5[] = { v8::Null() }; -+ Local<Value> value_obj5 = instance->CallAsConstructor(1, args5); -+ CHECK(value_obj5->IsObject()); -+ Local<Object> object5 = Local<Object>::Cast(value_obj5); -+ value = object5->Get(v8_str("a")); -+ CHECK(!try_catch.HasCaught()); -+ CHECK(value->IsNull()); -+ } -+ -+ // Check exception handling when there is no constructor set for the Object. -+ { Local<ObjectTemplate> instance_template = ObjectTemplate::New(); -+ Local<Object> instance = instance_template->NewInstance(); -+ context->Global()->Set(v8_str("obj2"), instance); -+ v8::TryCatch try_catch; -+ Local<Value> value; -+ CHECK(!try_catch.HasCaught()); -+ -+ value = CompileRun("new obj2(28)"); -+ CHECK(try_catch.HasCaught()); -+ String::AsciiValue exception_value1(try_catch.Exception()); -+ CHECK_EQ("TypeError: object is not a function", *exception_value1); -+ try_catch.Reset(); -+ -+ Local<Value> args[] = { v8_num(29) }; -+ value = instance->CallAsConstructor(1, args); -+ CHECK(try_catch.HasCaught()); -+ String::AsciiValue exception_value2(try_catch.Exception()); -+ CHECK_EQ("TypeError: #<Object> is not a function", *exception_value2); -+ try_catch.Reset(); -+ } -+ -+ // Check the case when constructor throws exception. -+ { Local<ObjectTemplate> instance_template = ObjectTemplate::New(); -+ instance_template->SetCallAsFunctionHandler(ThrowValue); -+ Local<Object> instance = instance_template->NewInstance(); -+ context->Global()->Set(v8_str("obj3"), instance); -+ v8::TryCatch try_catch; -+ Local<Value> value; -+ CHECK(!try_catch.HasCaught()); -+ -+ value = CompileRun("new obj3(22)"); -+ CHECK(try_catch.HasCaught()); -+ String::AsciiValue exception_value1(try_catch.Exception()); -+ CHECK_EQ("22", *exception_value1); -+ try_catch.Reset(); -+ -+ Local<Value> args[] = { v8_num(23) }; -+ value = instance->CallAsConstructor(1, args); -+ CHECK(try_catch.HasCaught()); -+ String::AsciiValue exception_value2(try_catch.Exception()); -+ CHECK_EQ("23", *exception_value2); -+ try_catch.Reset(); -+ } -+ -+ // Check whether constructor returns with an object or non-object. -+ { Local<FunctionTemplate> function_template = -+ FunctionTemplate::New(FakeConstructorCallback); -+ Local<Function> function = function_template->GetFunction(); -+ Local<Object> instance1 = function; -+ context->Global()->Set(v8_str("obj4"), instance1); -+ v8::TryCatch try_catch; -+ Local<Value> value; -+ CHECK(!try_catch.HasCaught()); -+ -+ CHECK(instance1->IsObject()); -+ CHECK(instance1->IsFunction()); -+ -+ value = CompileRun("new obj4(28)"); -+ CHECK(!try_catch.HasCaught()); -+ CHECK(value->IsObject()); -+ -+ Local<Value> args1[] = { v8_num(28) }; -+ value = instance1->CallAsConstructor(1, args1); -+ CHECK(!try_catch.HasCaught()); -+ CHECK(value->IsObject()); -+ -+ Local<ObjectTemplate> instance_template = ObjectTemplate::New(); -+ instance_template->SetCallAsFunctionHandler(FakeConstructorCallback); -+ Local<Object> instance2 = instance_template->NewInstance(); -+ context->Global()->Set(v8_str("obj5"), instance2); -+ CHECK(!try_catch.HasCaught()); -+ -+ CHECK(instance2->IsObject()); -+ CHECK(!instance2->IsFunction()); -+ -+ value = CompileRun("new obj5(28)"); -+ CHECK(!try_catch.HasCaught()); -+ CHECK(!value->IsObject()); -+ -+ Local<Value> args2[] = { v8_num(28) }; -+ value = instance2->CallAsConstructor(1, args2); -+ CHECK(!try_catch.HasCaught()); -+ CHECK(!value->IsObject()); -+ } -+} -+ -+ - THREADED_TEST(FunctionDescriptorException) { - v8::HandleScope handle_scope; - LocalContext context; -@@ -7028,9 +7222,8 @@ THREADED_TEST(CallAsFunction) { - CHECK(value.IsEmpty()); - CHECK(try_catch.HasCaught()); - String::AsciiValue exception_value1(try_catch.Exception()); -- CHECK_EQ(*exception_value1, -- "TypeError: Property 'obj2' of object " -- "#<Object> is not a function"); -+ CHECK_EQ("TypeError: Property 'obj2' of object #<Object> is not a function", -+ *exception_value1); - try_catch.Reset(); - - // Call an object without call-as-function handler through the API -@@ -7040,7 +7233,7 @@ THREADED_TEST(CallAsFunction) { - CHECK(value.IsEmpty()); - CHECK(try_catch.HasCaught()); - String::AsciiValue exception_value2(try_catch.Exception()); -- CHECK_EQ(*exception_value2, "TypeError: [object Object] is not a function"); -+ CHECK_EQ("TypeError: [object Object] is not a function", *exception_value2); - try_catch.Reset(); - } - -@@ -7057,14 +7250,14 @@ THREADED_TEST(CallAsFunction) { - value = CompileRun("obj3(22)"); - CHECK(try_catch.HasCaught()); - String::AsciiValue exception_value1(try_catch.Exception()); -- CHECK_EQ(*exception_value1, "22"); -+ CHECK_EQ("22", *exception_value1); - try_catch.Reset(); - - v8::Handle<Value> args[] = { v8_num(23) }; - value = instance->CallAsFunction(instance, 1, args); - CHECK(try_catch.HasCaught()); - String::AsciiValue exception_value2(try_catch.Exception()); -- CHECK_EQ(*exception_value2, "23"); -+ CHECK_EQ("23", *exception_value2); - try_catch.Reset(); - } - } --- -1.7.4.4 - diff --git a/src/v8/0013-Remove-execute-flag-from-v8-debug.h.patch b/src/v8/0010-Remove-execute-flag-from-v8-debug.h.patch index 9d987dd3c1..b353f5fcca 100644 --- a/src/v8/0013-Remove-execute-flag-from-v8-debug.h.patch +++ b/src/v8/0010-Remove-execute-flag-from-v8-debug.h.patch @@ -1,7 +1,7 @@ -From c36be227e9d7952a1952caa529c78ecdc376bd55 Mon Sep 17 00:00:00 2001 +From 8796bc9571db9f7049c96a9829281fedc54f8f38 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 13/16] Remove execute flag from v8-debug.h +Subject: [PATCH 10/11] Remove execute flag from v8-debug.h --- 0 files changed, 0 insertions(+), 0 deletions(-) diff --git a/src/v8/0007-Fix-warnings.patch b/src/v8/0011-Fix-warnings.patch index b4e39cc521..37f4043a30 100644 --- a/src/v8/0007-Fix-warnings.patch +++ b/src/v8/0011-Fix-warnings.patch @@ -1,18 +1,18 @@ -From 2a5cf85d7fd7912e516138db03e4cda47cc2a1ab Mon Sep 17 00:00:00 2001 +From 9c0d93bfae724e29ef63456942d9ddca10ca5825 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 07/16] Fix warnings +Subject: [PATCH 11/11] Fix warnings --- include/v8.h | 16 ++++++++-------- 1 files changed, 8 insertions(+), 8 deletions(-) diff --git a/include/v8.h b/include/v8.h -index 2bc0ed1..99f4b9a 100644 +index d995e54..a7b5c8a 100644 --- a/include/v8.h +++ b/include/v8.h -@@ -2416,7 +2416,7 @@ class V8EXPORT Extension { // NOLINT - const char** deps = 0); +@@ -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) { @@ -20,7 +20,7 @@ index 2bc0ed1..99f4b9a 100644 return v8::Handle<v8::FunctionTemplate>(); } -@@ -3722,13 +3722,13 @@ class Internals { +@@ -3946,13 +3946,13 @@ class Internals { return *reinterpret_cast<T*>(addr); } diff --git a/src/v8/0012-Add-IsCallable-method-for-Object-in-the-API.patch b/src/v8/0012-Add-IsCallable-method-for-Object-in-the-API.patch deleted file mode 100644 index 412cebd4d7..0000000000 --- a/src/v8/0012-Add-IsCallable-method-for-Object-in-the-API.patch +++ /dev/null @@ -1,116 +0,0 @@ -From a338d96fe138fbffd4b45c7d13a54e068daa6e12 Mon Sep 17 00:00:00 2001 -From: ager@chromium.org <ager@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00> -Date: Mon, 9 May 2011 15:24:48 +0000 -Subject: [PATCH 12/16] Add IsCallable method for Object in the API - -Patch by Peter Varga. - -BUG=none -TEST=cctest/test-api/CallableObject - -Review URL: http://codereview.chromium.org/6964005 - -git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@7828 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 ---- - include/v8.h | 7 +++++++ - src/api.cc | 11 +++++++++++ - test/cctest/test-api.cc | 43 +++++++++++++++++++++++++++++++++++++++++++ - 3 files changed, 61 insertions(+), 0 deletions(-) - -diff --git a/include/v8.h b/include/v8.h -index 43e00f5..5e1ce50 100644 ---- a/include/v8.h -+++ b/include/v8.h -@@ -1764,6 +1764,13 @@ class Object : public Value { - V8EXPORT int GetIndexedPropertiesExternalArrayDataLength(); - - /** -+ * Checks whether a callback is set by the -+ * ObjectTemplate::SetCallAsFunctionHandler method. -+ * When an Object is callable this method returns true. -+ */ -+ V8EXPORT bool IsCallable(); -+ -+ /** - * Call an Object as a function if a callback is set by the - * ObjectTemplate::SetCallAsFunctionHandler method. - */ -diff --git a/src/api.cc b/src/api.cc -index bd435eb..a5a637f 100644 ---- a/src/api.cc -+++ b/src/api.cc -@@ -3265,6 +3265,17 @@ int v8::Object::GetIndexedPropertiesExternalArrayDataLength() { - } - - -+bool v8::Object::IsCallable() { -+ i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); -+ ON_BAILOUT(isolate, "v8::Object::IsCallable()", return false); -+ ENTER_V8(isolate); -+ i::HandleScope scope(isolate); -+ i::Handle<i::JSObject> obj = Utils::OpenHandle(this); -+ if (obj->IsJSFunction()) return true; -+ return i::Execution::GetFunctionDelegate(obj)->IsJSFunction(); -+} -+ -+ - Local<v8::Value> Object::CallAsFunction(v8::Handle<v8::Object> recv, int argc, - v8::Handle<v8::Value> argv[]) { - i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); -diff --git a/test/cctest/test-api.cc b/test/cctest/test-api.cc -index 1334f63..45db5a1 100644 ---- a/test/cctest/test-api.cc -+++ b/test/cctest/test-api.cc -@@ -7263,6 +7263,49 @@ THREADED_TEST(CallAsFunction) { - } - - -+// Check whether a non-function object is callable. -+THREADED_TEST(CallableObject) { -+ v8::HandleScope scope; -+ LocalContext context; -+ -+ { Local<ObjectTemplate> instance_template = ObjectTemplate::New(); -+ instance_template->SetCallAsFunctionHandler(call_as_function); -+ Local<Object> instance = instance_template->NewInstance(); -+ v8::TryCatch try_catch; -+ -+ CHECK(instance->IsCallable()); -+ CHECK(!try_catch.HasCaught()); -+ } -+ -+ { Local<ObjectTemplate> instance_template = ObjectTemplate::New(); -+ Local<Object> instance = instance_template->NewInstance(); -+ v8::TryCatch try_catch; -+ -+ CHECK(!instance->IsCallable()); -+ CHECK(!try_catch.HasCaught()); -+ } -+ -+ { Local<FunctionTemplate> function_template = -+ FunctionTemplate::New(call_as_function); -+ Local<Function> function = function_template->GetFunction(); -+ Local<Object> instance = function; -+ v8::TryCatch try_catch; -+ -+ CHECK(instance->IsCallable()); -+ CHECK(!try_catch.HasCaught()); -+ } -+ -+ { Local<FunctionTemplate> function_template = FunctionTemplate::New(); -+ Local<Function> function = function_template->GetFunction(); -+ Local<Object> instance = function; -+ v8::TryCatch try_catch; -+ -+ CHECK(instance->IsCallable()); -+ CHECK(!try_catch.HasCaught()); -+ } -+} -+ -+ - static int CountHandles() { - return v8::HandleScope::NumberOfHandles(); - } --- -1.7.4.4 - diff --git a/src/v8/0016-Move-external-resource-to-the-last-hidden-field.patch b/src/v8/0016-Move-external-resource-to-the-last-hidden-field.patch deleted file mode 100644 index b6dde1e024..0000000000 --- a/src/v8/0016-Move-external-resource-to-the-last-hidden-field.patch +++ /dev/null @@ -1,61 +0,0 @@ -From 8f15248619bb3bf49473dc3ede8a4e631bd5d199 Mon Sep 17 00:00:00 2001 -From: Aaron Kennedy <aaron.kennedy@nokia.com> -Date: Tue, 4 Oct 2011 14:22:54 +1000 -Subject: [PATCH 16/16] Move external resource to the last hidden field - ---- - src/objects-inl.h | 10 +++++----- - 1 files changed, 5 insertions(+), 5 deletions(-) - -diff --git a/src/objects-inl.h b/src/objects-inl.h -index 1765441..c02e037 100644 ---- a/src/objects-inl.h -+++ b/src/objects-inl.h -@@ -1398,7 +1398,7 @@ int JSObject::GetInternalFieldCount() { - - int JSObject::GetInternalFieldOffset(int index) { - ASSERT(index < GetInternalFieldCount() && index >= 0); -- return GetHeaderSize() + (kPointerSize * (index + map()->has_external_resource()?1:0)); -+ return GetHeaderSize() + (kPointerSize * index); - } - - -@@ -1407,7 +1407,7 @@ Object* JSObject::GetInternalField(int index) { - // Internal objects do follow immediately after the header, whereas in-object - // properties are at the end of the object. Therefore there is no need - // to adjust the index here. -- return READ_FIELD(this, GetHeaderSize() + (kPointerSize * (index + map()->has_external_resource()?1:0))); -+ return READ_FIELD(this, GetHeaderSize() + (kPointerSize * index)); - } - - -@@ -1416,7 +1416,7 @@ void JSObject::SetInternalField(int index, Object* value) { - // Internal objects do follow immediately after the header, whereas in-object - // properties are at the end of the object. Therefore there is no need - // to adjust the index here. -- int offset = GetHeaderSize() + (kPointerSize * (index + map()->has_external_resource()?1:0)); -+ int offset = GetHeaderSize() + (kPointerSize * index); - WRITE_FIELD(this, offset, value); - WRITE_BARRIER(this, offset); - } -@@ -1424,7 +1424,7 @@ void JSObject::SetInternalField(int index, Object* value) { - - void JSObject::SetExternalResourceObject(Object *value) { - ASSERT(map()->has_external_resource()); -- int offset = GetHeaderSize(); -+ int offset = GetHeaderSize() + kPointerSize * GetInternalFieldCount(); - WRITE_FIELD(this, offset, value); - WRITE_BARRIER(this, offset); - } -@@ -1432,7 +1432,7 @@ void JSObject::SetExternalResourceObject(Object *value) { - - Object *JSObject::GetExternalResourceObject() { - if (map()->has_external_resource()) { -- return READ_FIELD(this, GetHeaderSize()); -+ return READ_FIELD(this, GetHeaderSize() + kPointerSize * GetInternalFieldCount()); - } else { - return GetHeap()->undefined_value(); - } --- -1.7.4.4 - diff --git a/src/v8/README b/src/v8/README index 2dc39705aa..2cf8611831 100644 --- a/src/v8/README +++ b/src/v8/README @@ -1 +1 @@ -These patches apply cleanly against v8 at 2eaa4b29586fdbd5d41f7b7d9e72ecca6d53dbd2 +These patches apply cleanly against v8 at bd43701b639856950d7cb461d777193a51c4859c diff --git a/src/v8/v8.pri b/src/v8/v8.pri index 1d1abc85c0..2d369d9166 100644 --- a/src/v8/v8.pri +++ b/src/v8/v8.pri @@ -72,10 +72,10 @@ SOURCES += \ $$V8SRC/disassembler.cc \ $$V8SRC/diy-fp.cc \ $$V8SRC/dtoa.cc \ + $$V8SRC/elements.cc \ $$V8SRC/execution.cc \ $$V8SRC/factory.cc \ $$V8SRC/flags.cc \ - $$V8SRC/frame-element.cc \ $$V8SRC/frames.cc \ $$V8SRC/full-codegen.cc \ $$V8SRC/func-name-inferrer.cc \ @@ -90,6 +90,7 @@ SOURCES += \ $$V8SRC/hydrogen.cc \ $$V8SRC/hydrogen-instructions.cc \ $$V8SRC/ic.cc \ + $$V8SRC/incremental-marking.cc \ $$V8SRC/inspector.cc \ $$V8SRC/interpreter-irregexp.cc \ $$V8SRC/isolate.cc \ @@ -117,8 +118,8 @@ SOURCES += \ $$V8SRC/runtime.cc \ $$V8SRC/runtime-profiler.cc \ $$V8SRC/safepoint-table.cc \ - $$V8SRC/scanner-base.cc \ $$V8SRC/scanner.cc \ + $$V8SRC/scanner-character-streams.cc \ $$V8SRC/scopeinfo.cc \ $$V8SRC/scopes.cc \ $$V8SRC/serialize.cc \ @@ -129,15 +130,17 @@ SOURCES += \ $$V8SRC/strtod.cc \ $$V8SRC/stub-cache.cc \ $$V8SRC/token.cc \ - $$V8SRC/top.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 @@ -258,7 +261,11 @@ V8_LIBRARY_FILES = \ $$V8SRC/mirror-debugger.js \ $$V8SRC/debug-debugger.js -v8_js2c.commands = python $$V8DIR/tools/js2c.py $$V8_GENERATED_SOURCES_DIR/libraries.cpp $$V8_GENERATED_SOURCES_DIR/libraries-empty.cpp CORE +V8_EXPERIMENTAL_LIBRARY_FILES = \ + $$V8SRC/proxy.js \ + $$V8SRC/weakmap.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 @@ -268,4 +275,15 @@ 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 -QMAKE_EXTRA_COMPILERS += v8_js2c + +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 diff --git a/tests/auto/v8/tst_v8.cpp b/tests/auto/v8/tst_v8.cpp index c753806518..fcb49f84e0 100644 --- a/tests/auto/v8/tst_v8.cpp +++ b/tests/auto/v8/tst_v8.cpp @@ -57,6 +57,7 @@ private slots: void eval(); void evalwithinwith(); void userobjectcompare(); + void externalteardown(); }; void tst_v8::eval() @@ -74,6 +75,11 @@ void tst_v8::userobjectcompare() QVERIFY(v8test_userobjectcompare()); } +void tst_v8::externalteardown() +{ + QVERIFY(v8test_externalteardown()); +} + int main(int argc, char *argv[]) { V8::SetFlagsFromCommandLine(&argc, argv, true); diff --git a/tests/auto/v8/v8main.cpp b/tests/auto/v8/v8main.cpp index b38bbabbd5..882c2b99bb 100644 --- a/tests/auto/v8/v8main.cpp +++ b/tests/auto/v8/v8main.cpp @@ -45,6 +45,8 @@ #define RUN_TEST(testname) { \ if (!v8test_ ## testname()) \ printf ("Test %s FAILED\n", # testname); \ + else \ + printf ("Test %s PASS\n", # testname); \ } int main(int argc, char *argv[]) @@ -54,6 +56,7 @@ int main(int argc, char *argv[]) RUN_TEST(eval); RUN_TEST(evalwithinwith); RUN_TEST(userobjectcompare); + RUN_TEST(externalteardown); return -1; } diff --git a/tests/auto/v8/v8test.cpp b/tests/auto/v8/v8test.cpp index 0b299ed23c..b2734af8c3 100644 --- a/tests/auto/v8/v8test.cpp +++ b/tests/auto/v8/v8test.cpp @@ -54,6 +54,59 @@ using namespace v8; } \ } +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); + + Local<String> str = 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() { diff --git a/tests/auto/v8/v8test.h b/tests/auto/v8/v8test.h index fa9bbe9f02..cb737971cb 100644 --- a/tests/auto/v8/v8test.h +++ b/tests/auto/v8/v8test.h @@ -51,6 +51,7 @@ bool v8test_eval(); bool v8test_evalwithinwith(); bool v8test_userobjectcompare(); +bool v8test_externalteardown(); #endif // V8TEST_H |