diff options
Diffstat (limited to 'src')
20 files changed, 1796 insertions, 2807 deletions
diff --git a/src/3rdparty/v8 b/src/3rdparty/v8 -Subproject 8f15248619bb3bf49473dc3ede8a4e631bd5d19 +Subproject 36be1e6b4af4601faa40ea4a222539c6b48f0e0 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..7172cbf703 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 0a86a97f554c4aaa727da1c4481ca6368c68bf85 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 ac4f07f..996812e 100644 --- a/src/api.cc +++ b/src/api.cc -@@ -3284,6 +3284,49 @@ int String::Utf8Length() const { - return str->Utf8Length(); +@@ -3633,6 +3633,57 @@ int String::Utf8Length() const { } + +uint32_t String::Hash() const { + i::Handle<i::String> str = Utils::OpenHandle(this); + if (IsDeadCheck(str->GetIsolate(), "v8::String::Hash()")) return 0; + return str->Hash(); +} + ++ +String::CompleteHashData String::CompleteHash() const { + i::Handle<i::String> str = Utils::OpenHandle(this); + if (IsDeadCheck(str->GetIsolate(), "v8::String::CompleteHash()")) return CompleteHashData(); @@ -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 aaf2927..4c55d63 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 bbb9d3e..d287ead 100644 --- a/src/heap.cc +++ b/src/heap.cc -@@ -3519,6 +3519,7 @@ MaybeObject* Heap::AllocateInternalSymbol(unibrow::CharacterStream* buffer, +@@ -4009,6 +4009,7 @@ MaybeObject* Heap::AllocateInternalSymbol(unibrow::CharacterStream* buffer, String* answer = String::cast(result); answer->set_length(chars); answer->set_hash_field(hash_field); -+ SeqString::cast(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) { +@@ -4051,6 +4052,7 @@ MaybeObject* Heap::AllocateRawAsciiString(int length, PretenureFlag pretenure) { HeapObject::cast(result)->set_map(ascii_string_map()); String::cast(result)->set_length(length); String::cast(result)->set_hash_field(String::kEmptyHashField); @@ -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, +@@ -4086,6 +4088,7 @@ MaybeObject* Heap::AllocateRawTwoByteString(int length, HeapObject::cast(result)->set_map(string_map()); String::cast(result)->set_length(length); String::cast(result)->set_hash_field(String::kEmptyHashField); @@ -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 dc3aa46..34cae9f 100644 --- a/src/objects-inl.h +++ b/src/objects-inl.h -@@ -1924,6 +1924,7 @@ INT_ACCESSORS(ExternalArray, length, kLengthOffset) - +@@ -2082,6 +2082,7 @@ SMI_ACCESSORS(FixedArrayBase, length, kLengthOffset) + SMI_ACCESSORS(FreeSpace, size, kSizeOffset) SMI_ACCESSORS(String, length, kLengthOffset) +SMI_ACCESSORS(SeqString, symbol_id, kSymbolIdOffset) @@ -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 9a87ac5..2946d02 100644 --- a/src/objects.cc +++ b/src/objects.cc -@@ -5346,6 +5346,66 @@ static inline bool CompareStringContentsPartial(Isolate* isolate, - } +@@ -6716,6 +6716,71 @@ static inline bool CompareStringContentsPartial(Isolate* isolate, } + +bool String::SlowEqualsExternal(uc16 *string, int length) { + int len = this->length(); + if (len != length) return false; @@ -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(); +@@ -10716,9 +10781,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 f7d2180..d96e5f9 100644 --- a/src/objects.h +++ b/src/objects.h -@@ -5359,6 +5359,9 @@ class String: public HeapObject { +@@ -6201,6 +6201,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: +@@ -6457,8 +6460,13 @@ class SeqString: public String { + // Casting. + static inline SeqString* cast(Object* obj); + // Get and set the symbol id of the string + inline int symbol_id(); + inline void set_symbol_id(int value); + - // 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. + private: + DISALLOW_IMPLICIT_CONSTRUCTORS(SeqString); -- 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..d30dc470dd 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 20eca1d4ce4c56b599a052d496f4660f9ca9c978 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: Thu, 27 Oct 2011 11:31:56 +0100 +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 996812e..e0f3b5a 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 15f640e..1b95ed1 100644 --- a/src/factory.cc +++ b/src/factory.cc -@@ -1058,6 +1058,10 @@ Handle<JSFunction> Factory::CreateApiFunction( +@@ -1213,6 +1213,9 @@ Handle<JSFunction> Factory::CreateApiFunction( // Set interceptor information in the map. if (!obj->named_property_handler()->IsUndefined()) { map->set_has_named_interceptor(); -+ + InterceptorInfo *nph = InterceptorInfo::cast(obj->named_property_handler()); + bool is_fallback = nph->is_fallback()->IsUndefined()?false:nph->is_fallback()->value(); + map->set_named_interceptor_is_fallback(is_fallback); @@ -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 62851f3..790d224 100644 --- a/src/handles.cc +++ b/src/handles.cc -@@ -262,9 +262,11 @@ Handle<Object> SetProperty(Handle<JSObject> object, +@@ -269,9 +269,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 06e47fc..c359cb3 100644 --- a/src/handles.h +++ b/src/handles.h -@@ -188,7 +188,8 @@ Handle<Object> SetProperty(Handle<JSObject> object, +@@ -190,7 +190,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 34cae9f..1cfea84 100644 --- a/src/objects-inl.h +++ b/src/objects-inl.h -@@ -2521,6 +2521,21 @@ bool Map::is_shared() { +@@ -2754,6 +2754,20 @@ void Map::set_is_shared(bool value) { + bool Map::is_shared() { + return ((1 << kIsShared) & bit_field3()) != 0; } - - ++ +void Map::set_named_interceptor_is_fallback(bool value) +{ + if (value) { @@ -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) +@@ -3255,6 +3269,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 2946d02..f5b6bee 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) { - LookupResult result; +@@ -1980,9 +1980,10 @@ MaybeObject* JSObject::SetPropertyWithInterceptor( + MaybeObject* JSReceiver::SetProperty(String* name, + Object* value, + PropertyAttributes attributes, +- StrictModeFlag strict_mode) { ++ StrictModeFlag strict_mode, ++ bool skip_fallback_interceptor) { + LookupResult result(GetIsolate()); - LocalLookup(name, &result); + LocalLookup(name, &result, skip_fallback_interceptor); return SetProperty(&result, name, value, attributes, strict_mode); } -@@ -3148,7 +3149,8 @@ AccessorDescriptor* Map::FindAccessor(String* name) { +@@ -4213,7 +4214,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) { +@@ -4245,23 +4247,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 d96e5f9..ed40061 100644 --- a/src/objects.h +++ b/src/objects.h -@@ -1405,7 +1405,8 @@ class JSObject: public HeapObject { +@@ -1362,7 +1362,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 { +@@ -1414,8 +1415,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(); +@@ -4242,6 +4243,10 @@ class Map: public HeapObject { inline void set_is_access_check_needed(bool access_check_needed); inline bool is_access_check_needed(); -+ + // Whether the named interceptor is a fallback interceptor or not + inline void set_named_interceptor_is_fallback(bool value); + inline bool named_interceptor_is_fallback(); + -+ // [prototype]: implicit prototype object. DECL_ACCESSORS(prototype, Object) -@@ -3904,6 +3911,7 @@ class Map: public HeapObject { - static const int kHasExternalArrayElements = 6; +@@ -4506,6 +4511,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 { +@@ -7390,6 +7396,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 { +@@ -7409,7 +7416,8 @@ class InterceptorInfo: public Struct { static const int kDeleterOffset = kQueryOffset + kPointerSize; static const int kEnumeratorOffset = kDeleterOffset + kPointerSize; static const int kDataOffset = kEnumeratorOffset + kPointerSize; @@ -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 9c23c2c..0e256c1 100644 --- a/src/runtime.cc +++ b/src/runtime.cc -@@ -1097,7 +1097,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareGlobals) { +@@ -1330,7 +1330,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareGlobals) { // Lookup the property in the global object, and don't set the // value of the variable if the property is already there. - LookupResult lookup; + LookupResult lookup(isolate); - 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. +@@ -1357,7 +1357,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareGlobals) { } - LookupResult lookup; + LookupResult lookup(isolate); - 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 +@@ -1398,7 +1398,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) { - +@@ -1534,7 +1535,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeVarGlobal) { + while (object->IsJSObject() && + JSObject::cast(object)->map()->is_hidden_prototype()) { + JSObject* raw_holder = JSObject::cast(object); +- raw_holder->LocalLookup(*name, &lookup); ++ raw_holder->LocalLookup(*name, &lookup, true); + if (lookup.IsProperty() && lookup.type() == INTERCEPTOR) { + HandleScope handle_scope(isolate); + Handle<JSObject> holder(raw_holder); +@@ -1557,7 +1558,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeVarGlobal) { + // Reload global in case the loop above performed a GC. global = isolate->context()->global(); if (assign) { - return global->SetProperty(*name, args[2], attributes, strict_mode); 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..7d532c4a4c --- /dev/null +++ b/src/v8/0003-Generalize-external-object-resources.patch @@ -0,0 +1,595 @@ +From 74974cee335e6c22ea99fd9a4bbb9c7fa7323d80 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 e0f3b5a..7d54252 100644 +--- a/src/api.cc ++++ b/src/api.cc +@@ -1436,6 +1436,34 @@ void ObjectTemplate::SetInternalFieldCount(int value) { + } + + ++bool ObjectTemplate::HasExternalResource() ++{ ++ if (IsDeadCheck(Utils::OpenHandle(this)->GetIsolate(), ++ "v8::ObjectTemplate::HasExternalResource()")) { ++ return 0; ++ } ++ return !Utils::OpenHandle(this)->has_external_resource()->IsUndefined(); ++} ++ ++ ++void ObjectTemplate::SetHasExternalResource(bool value) ++{ ++ i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); ++ if (IsDeadCheck(isolate, "v8::ObjectTemplate::SetHasExternalResource()")) { ++ return; ++ } ++ ENTER_V8(isolate); ++ if (value) { ++ EnsureConstructor(this); ++ } ++ if (value) { ++ Utils::OpenHandle(this)->set_has_external_resource(i::Smi::FromInt(1)); ++ } else { ++ Utils::OpenHandle(this)->set_has_external_resource(Utils::OpenHandle(this)->GetHeap()->undefined_value()); ++ } ++} ++ ++ + // --- S c r i p t D a t a --- + + +@@ -4029,6 +4057,34 @@ void v8::Object::SetPointerInInternalField(int index, void* value) { + } + + ++void v8::Object::SetExternalResource(v8::Object::ExternalResource *resource) { ++ i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); ++ ENTER_V8(isolate); ++ i::Handle<i::JSObject> obj = Utils::OpenHandle(this); ++ if (CanBeEncodedAsSmi(resource)) { ++ obj->SetExternalResourceObject(EncodeAsSmi(resource)); ++ } else { ++ obj->SetExternalResourceObject(*isolate->factory()->NewForeign(static_cast<i::Address>((void *)resource))); ++ } ++ if (!obj->IsSymbol()) { ++ isolate->heap()->external_string_table()->AddObject(*obj); ++ } ++} ++ ++ ++v8::Object::ExternalResource *v8::Object::GetExternalResource() { ++ i::Handle<i::JSObject> obj = Utils::OpenHandle(this); ++ i::Object* value = obj->GetExternalResourceObject(); ++ if (value->IsSmi()) { ++ return reinterpret_cast<v8::Object::ExternalResource*>(i::Internals::GetExternalPointerFromSmi(value)); ++ } else if (value->IsForeign()) { ++ return reinterpret_cast<v8::Object::ExternalResource*>(i::Foreign::cast(value)->address()); ++ } else { ++ return NULL; ++ } ++} ++ ++ + // --- E n v i r o n m e n t --- + + +diff --git a/src/factory.cc b/src/factory.cc +index 1b95ed1..8c96944 100644 +--- a/src/factory.cc ++++ b/src/factory.cc +@@ -1152,15 +1152,21 @@ Handle<JSFunction> Factory::CreateApiFunction( + Handle<Code> construct_stub = isolate()->builtins()->JSConstructStubApi(); + + int internal_field_count = 0; ++ bool has_external_resource = false; ++ + if (!obj->instance_template()->IsUndefined()) { + Handle<ObjectTemplateInfo> instance_template = + Handle<ObjectTemplateInfo>( + ObjectTemplateInfo::cast(obj->instance_template())); + internal_field_count = + Smi::cast(instance_template->internal_field_count())->value(); ++ has_external_resource = ++ !instance_template->has_external_resource()->IsUndefined(); + } + + int instance_size = kPointerSize * internal_field_count; ++ if (has_external_resource) instance_size += kPointerSize; ++ + InstanceType type = INVALID_TYPE; + switch (instance_type) { + case JavaScriptObject: +@@ -1195,6 +1201,11 @@ Handle<JSFunction> Factory::CreateApiFunction( + + Handle<Map> map = Handle<Map>(result->initial_map()); + ++ // Mark as having external data object if needed ++ if (has_external_resource) { ++ map->set_has_external_resource(true); ++ } ++ + // Mark as undetectable if needed. + if (obj->undetectable()) { + map->set_is_undetectable(); +diff --git a/src/heap-inl.h b/src/heap-inl.h +index 4c55d63..bca57cb 100644 +--- a/src/heap-inl.h ++++ b/src/heap-inl.h +@@ -222,21 +222,36 @@ MaybeObject* Heap::NumberFromUint32(uint32_t value) { + } + + +-void Heap::FinalizeExternalString(String* string) { +- ASSERT(string->IsExternalString()); +- v8::String::ExternalStringResourceBase** resource_addr = +- reinterpret_cast<v8::String::ExternalStringResourceBase**>( +- reinterpret_cast<byte*>(string) + +- ExternalString::kResourceOffset - +- kHeapObjectTag); +- +- // Dispose of the C++ object if it has not already been disposed. +- if (*resource_addr != NULL) { +- (*resource_addr)->Dispose(); ++void Heap::FinalizeExternalString(HeapObject* string) { ++ ASSERT(string->IsExternalString() || string->map()->has_external_resource()); ++ ++ if (string->IsExternalString()) { ++ v8::String::ExternalStringResourceBase** resource_addr = ++ reinterpret_cast<v8::String::ExternalStringResourceBase**>( ++ reinterpret_cast<byte*>(string) + ++ ExternalString::kResourceOffset - ++ kHeapObjectTag); ++ ++ // Dispose of the C++ object if it has not already been disposed. ++ if (*resource_addr != NULL) { ++ (*resource_addr)->Dispose(); ++ } ++ ++ // Clear the resource pointer in the string. ++ *resource_addr = NULL; ++ } else { ++ JSObject *object = JSObject::cast(string); ++ Object *value = object->GetExternalResourceObject(); ++ v8::Object::ExternalResource *resource = 0; ++ if (value->IsSmi()) { ++ resource = reinterpret_cast<v8::Object::ExternalResource*>(Internals::GetExternalPointerFromSmi(value)); ++ } else if (value->IsForeign()) { ++ resource = reinterpret_cast<v8::Object::ExternalResource*>(Foreign::cast(value)->address()); ++ } ++ if (resource) { ++ resource->Dispose(); ++ } + } +- +- // Clear the resource pointer in the string. +- *resource_addr = NULL; + } + + +@@ -555,6 +570,16 @@ void ExternalStringTable::AddString(String* string) { + } + + ++void ExternalStringTable::AddObject(HeapObject* object) { ++ ASSERT(object->map()->has_external_resource()); ++ if (heap_->InNewSpace(object)) { ++ new_space_strings_.Add(object); ++ } else { ++ old_space_strings_.Add(object); ++ } ++} ++ ++ + void ExternalStringTable::Iterate(ObjectVisitor* v) { + if (!new_space_strings_.is_empty()) { + Object** start = &new_space_strings_[0]; +@@ -583,14 +608,14 @@ void ExternalStringTable::Verify() { + } + + +-void ExternalStringTable::AddOldString(String* string) { +- ASSERT(string->IsExternalString()); +- ASSERT(!heap_->InNewSpace(string)); +- old_space_strings_.Add(string); ++void ExternalStringTable::AddOldObject(HeapObject* object) { ++ ASSERT(object->IsExternalString() || object->map()->has_external_resource()); ++ ASSERT(!heap_->InNewSpace(object)); ++ old_space_strings_.Add(object); + } + + +-void ExternalStringTable::ShrinkNewStrings(int position) { ++void ExternalStringTable::ShrinkNewObjects(int position) { + new_space_strings_.Rewind(position); + if (FLAG_verify_heap) { + Verify(); +diff --git a/src/heap.cc b/src/heap.cc +index d287ead..53a0f27 100644 +--- a/src/heap.cc ++++ b/src/heap.cc +@@ -1099,18 +1099,18 @@ void Heap::Scavenge() { + } + + +-String* Heap::UpdateNewSpaceReferenceInExternalStringTableEntry(Heap* heap, +- Object** p) { ++HeapObject* Heap::UpdateNewSpaceReferenceInExternalStringTableEntry(Heap* heap, ++ Object** p) { + MapWord first_word = HeapObject::cast(*p)->map_word(); + + if (!first_word.IsForwardingAddress()) { + // Unreachable external string can be finalized. +- heap->FinalizeExternalString(String::cast(*p)); ++ heap->FinalizeExternalString(HeapObject::cast(*p)); + return NULL; + } + + // String is still reachable. +- return String::cast(first_word.ToForwardingAddress()); ++ return HeapObject::cast(first_word.ToForwardingAddress()); + } + + +@@ -1128,11 +1128,11 @@ void Heap::UpdateNewSpaceReferencesInExternalStringTable( + + for (Object** p = start; p < end; ++p) { + ASSERT(InFromSpace(*p)); +- String* target = updater_func(this, p); ++ HeapObject* target = updater_func(this, p); + + if (target == NULL) continue; + +- ASSERT(target->IsExternalString()); ++ ASSERT(target->IsExternalString() || target->map()->has_external_resource()); + + if (InNewSpace(target)) { + // String is still in new space. Update the table entry. +@@ -1140,12 +1140,12 @@ void Heap::UpdateNewSpaceReferencesInExternalStringTable( + ++last; + } else { + // String got promoted. Move it to the old string list. +- external_string_table_.AddOldString(target); ++ external_string_table_.AddOldObject(target); + } + } + + ASSERT(last <= end); +- external_string_table_.ShrinkNewStrings(static_cast<int>(last - start)); ++ external_string_table_.ShrinkNewObjects(static_cast<int>(last - start)); + } + + +@@ -6367,6 +6367,19 @@ void ExternalStringTable::CleanUp() { + + + void ExternalStringTable::TearDown() { ++ for (int i = 0; i < new_space_strings_.length(); ++i) { ++ if (new_space_strings_[i] == heap_->raw_unchecked_null_value()) continue; ++ HeapObject *object = HeapObject::cast(new_space_strings_[i]); ++ if (!object->IsExternalString()) ++ heap_->FinalizeExternalString(object); ++ } ++ for (int i = 0; i < old_space_strings_.length(); ++i) { ++ if (old_space_strings_[i] == heap_->raw_unchecked_null_value()) continue; ++ HeapObject *object = HeapObject::cast(old_space_strings_[i]); ++ if (!object->IsExternalString()) ++ heap_->FinalizeExternalString(object); ++ } ++ + new_space_strings_.Free(); + old_space_strings_.Free(); + } +diff --git a/src/heap.h b/src/heap.h +index 7c0b0ea..5e90964 100644 +--- a/src/heap.h ++++ b/src/heap.h +@@ -245,8 +245,8 @@ class Isolate; + class WeakObjectRetainer; + + +-typedef String* (*ExternalStringTableUpdaterCallback)(Heap* heap, +- Object** pointer); ++typedef HeapObject* (*ExternalStringTableUpdaterCallback)(Heap* heap, ++ Object** pointer); + + class StoreBufferRebuilder { + public: +@@ -331,10 +331,14 @@ typedef void (*ScavengingCallback)(Map* map, + // External strings table is a place where all external strings are + // registered. We need to keep track of such strings to properly + // finalize them. ++// The ExternalStringTable can contain both strings and objects with ++// external resources. It was not renamed to make the patch simpler. + class ExternalStringTable { + public: + // Registers an external string. + inline void AddString(String* string); ++ // Registers an external object. ++ inline void AddObject(HeapObject* string); + + inline void Iterate(ObjectVisitor* v); + +@@ -352,10 +356,10 @@ class ExternalStringTable { + + inline void Verify(); + +- inline void AddOldString(String* string); ++ inline void AddOldObject(HeapObject* string); + + // Notifies the table that only a prefix of the new list is valid. +- inline void ShrinkNewStrings(int position); ++ inline void ShrinkNewObjects(int position); + + // To speed up scavenge collections new space string are kept + // separate from old space strings. +@@ -851,7 +855,7 @@ class Heap { + + // Finalizes an external string by deleting the associated external + // data and clearing the resource pointer. +- inline void FinalizeExternalString(String* string); ++ inline void FinalizeExternalString(HeapObject* string); + + // Allocates an uninitialized object. The memory is non-executable if the + // hardware and OS allow. +@@ -1656,7 +1660,7 @@ class Heap { + // Performs a minor collection in new generation. + void Scavenge(); + +- static String* UpdateNewSpaceReferenceInExternalStringTableEntry( ++ static HeapObject* UpdateNewSpaceReferenceInExternalStringTableEntry( + Heap* heap, + Object** pointer); + +diff --git a/src/mark-compact.cc b/src/mark-compact.cc +index b41b033..bf0aab8 100644 +--- a/src/mark-compact.cc ++++ b/src/mark-compact.cc +@@ -1513,8 +1513,9 @@ class SymbolTableCleaner : public ObjectVisitor { + + // Since no objects have yet been moved we can safely access the map of + // the object. +- if (o->IsExternalString()) { +- heap_->FinalizeExternalString(String::cast(*p)); ++ if (o->IsExternalString() || ++ (o->IsHeapObject() && HeapObject::cast(o)->map()->has_external_resource())) { ++ heap_->FinalizeExternalString(HeapObject::cast(*p)); + } + // Set the entry to null_value (as deleted). + *p = heap_->null_value(); +@@ -2487,15 +2488,15 @@ static void UpdatePointer(HeapObject** p, HeapObject* object) { + } + + +-static String* UpdateReferenceInExternalStringTableEntry(Heap* heap, +- Object** p) { ++static HeapObject* UpdateReferenceInExternalStringTableEntry(Heap* heap, ++ Object** p) { + MapWord map_word = HeapObject::cast(*p)->map_word(); + + if (map_word.IsForwardingAddress()) { +- return String::cast(map_word.ToForwardingAddress()); ++ return HeapObject::cast(map_word.ToForwardingAddress()); + } + +- return String::cast(*p); ++ return HeapObject::cast(*p); + } + + +diff --git a/src/objects-inl.h b/src/objects-inl.h +index 1cfea84..6a80c9c 100644 +--- a/src/objects-inl.h ++++ b/src/objects-inl.h +@@ -1343,7 +1343,7 @@ int JSObject::GetInternalFieldCount() { + // Make sure to adjust for the number of in-object properties. These + // properties do contribute to the size, but are not internal fields. + return ((Size() - GetHeaderSize()) >> kPointerSizeLog2) - +- map()->inobject_properties(); ++ map()->inobject_properties() - (map()->has_external_resource()?1:0); + } + + +@@ -1373,6 +1373,23 @@ void JSObject::SetInternalField(int index, Object* value) { + } + + ++void JSObject::SetExternalResourceObject(Object *value) { ++ ASSERT(map()->has_external_resource()); ++ int offset = GetHeaderSize() + kPointerSize * GetInternalFieldCount(); ++ WRITE_FIELD(this, offset, value); ++ WRITE_BARRIER(GetHeap(), this, offset, value); ++} ++ ++ ++Object *JSObject::GetExternalResourceObject() { ++ if (map()->has_external_resource()) { ++ return READ_FIELD(this, GetHeaderSize() + kPointerSize * GetInternalFieldCount()); ++ } else { ++ return GetHeap()->undefined_value(); ++ } ++} ++ ++ + // Access fast-case object properties at index. The use of these routines + // is needed to correctly distinguish between properties stored in-object and + // properties stored in the properties array. +@@ -2755,6 +2772,20 @@ bool Map::is_shared() { + return ((1 << kIsShared) & bit_field3()) != 0; + } + ++void Map::set_has_external_resource(bool value) { ++ if (value) { ++ set_bit_field(bit_field() | (1 << kHasExternalResource)); ++ } else { ++ set_bit_field(bit_field() & ~(1 << kHasExternalResource)); ++ } ++} ++ ++bool Map::has_external_resource() ++{ ++ return ((1 << kHasExternalResource) & bit_field()) != 0; ++} ++ ++ + void Map::set_named_interceptor_is_fallback(bool value) + { + if (value) { +@@ -3301,6 +3332,8 @@ ACCESSORS(FunctionTemplateInfo, flag, Smi, kFlagOffset) + ACCESSORS(ObjectTemplateInfo, constructor, Object, kConstructorOffset) + ACCESSORS(ObjectTemplateInfo, internal_field_count, Object, + kInternalFieldCountOffset) ++ACCESSORS(ObjectTemplateInfo, has_external_resource, Object, ++ kHasExternalResourceOffset) + + ACCESSORS(SignatureInfo, receiver, Object, kReceiverOffset) + ACCESSORS(SignatureInfo, args, Object, kArgsOffset) +diff --git a/src/objects.h b/src/objects.h +index ed40061..c38d461 100644 +--- a/src/objects.h ++++ b/src/objects.h +@@ -1760,6 +1760,9 @@ class JSObject: public JSReceiver { + inline Object* GetInternalField(int index); + inline void SetInternalField(int index, Object* value); + ++ inline void SetExternalResourceObject(Object *); ++ inline Object *GetExternalResourceObject(); ++ + // The following lookup functions skip interceptors. + void LocalLookupRealNamedProperty(String* name, LookupResult* result); + void LookupRealNamedProperty(String* name, LookupResult* result); +@@ -4171,11 +4174,11 @@ class Map: public HeapObject { + + // Tells whether the instance has a call-as-function handler. + inline void set_has_instance_call_handler() { +- set_bit_field(bit_field() | (1 << kHasInstanceCallHandler)); ++ set_bit_field3(bit_field3() | (1 << kHasInstanceCallHandler)); + } + + inline bool has_instance_call_handler() { +- return ((1 << kHasInstanceCallHandler) & bit_field()) != 0; ++ return ((1 << kHasInstanceCallHandler) & bit_field3()) != 0; + } + + inline void set_is_extensible(bool value); +@@ -4247,6 +4250,11 @@ class Map: public HeapObject { + inline void set_named_interceptor_is_fallback(bool value); + inline bool named_interceptor_is_fallback(); + ++ // Tells whether the instance has the space for an external resource ++ // object ++ inline void set_has_external_resource(bool value); ++ inline bool has_external_resource(); ++ + // [prototype]: implicit prototype object. + DECL_ACCESSORS(prototype, Object) + +@@ -4487,7 +4495,7 @@ class Map: public HeapObject { + static const int kHasNamedInterceptor = 3; + static const int kHasIndexedInterceptor = 4; + static const int kIsUndetectable = 5; +- static const int kHasInstanceCallHandler = 6; ++ static const int kHasExternalResource = 6; + static const int kIsAccessCheckNeeded = 7; + + // Bit positions for bit field 2 +@@ -4512,6 +4520,7 @@ class Map: public HeapObject { + // Bit positions for bit field 3 + static const int kIsShared = 0; + static const int kNamedInterceptorIsFallback = 1; ++ static const int kHasInstanceCallHandler = 2; + + // Layout of the default cache. It holds alternating name and code objects. + static const int kCodeCacheEntrySize = 2; +@@ -7539,6 +7548,7 @@ class ObjectTemplateInfo: public TemplateInfo { + public: + DECL_ACCESSORS(constructor, Object) + DECL_ACCESSORS(internal_field_count, Object) ++ DECL_ACCESSORS(has_external_resource, Object) + + static inline ObjectTemplateInfo* cast(Object* obj); + +@@ -7555,7 +7565,8 @@ class ObjectTemplateInfo: public TemplateInfo { + static const int kConstructorOffset = TemplateInfo::kHeaderSize; + static const int kInternalFieldCountOffset = + kConstructorOffset + kPointerSize; +- static const int kSize = kInternalFieldCountOffset + kPointerSize; ++ static const int kHasExternalResourceOffset = kInternalFieldCountOffset + kPointerSize; ++ static const int kSize = kHasExternalResourceOffset + kPointerSize; + }; + + +-- +1.7.4.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..8e91114ca4 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 6f97385cf3cb17d245e7f3d61ba975183a786220 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: Thu, 27 Oct 2011 13:34:16 +0100 +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,58 +15,60 @@ 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/lithium-arm.cc | 2 +- - src/arm/lithium-arm.h | 6 +++- - src/arm/lithium-codegen-arm.cc | 7 ++-- + src/arm/full-codegen-arm.cc | 28 +++++++++------- + src/arm/lithium-arm.cc | 4 +- + src/arm/lithium-arm.h | 12 ++++++- + src/arm/lithium-codegen-arm.cc | 9 +++-- src/arm/macro-assembler-arm.h | 5 +++ src/ast-inl.h | 5 +++ + src/ast.cc | 5 +++ 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/hydrogen.cc | 2 + - src/ia32/code-stubs-ia32.cc | 7 ++++ - src/ia32/full-codegen-ia32.cc | 26 ++++++++------ - src/ia32/lithium-codegen-ia32.cc | 7 ++-- - src/ia32/lithium-ia32.cc | 2 +- - src/ia32/lithium-ia32.h | 6 +++- - src/ia32/macro-assembler-ia32.h | 5 +++ - src/objects-inl.h | 12 ++++++ - src/objects.h | 5 +++ - src/parser.cc | 27 ++++++++++++-- + src/heap.cc | 4 ++ + src/hydrogen-instructions.cc | 5 +++ + src/hydrogen-instructions.h | 16 ++++++++- + src/hydrogen.cc | 4 ++ + src/ia32/code-stubs-ia32.cc | 5 +++ + src/ia32/full-codegen-ia32.cc | 28 +++++++++------- + src/ia32/lithium-codegen-ia32.cc | 9 +++-- + src/ia32/lithium-ia32.cc | 4 +- + src/ia32/lithium-ia32.h | 12 +++++- + src/ia32/macro-assembler-ia32.h | 3 ++ + src/objects-inl.h | 2 + + src/objects.h | 4 ++ + src/parser.cc | 28 +++++++++++++-- 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 | 63 +++++++++++++++++++++++++++++++++++ + 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/lithium-codegen-x64.cc | 7 ++-- - src/x64/lithium-x64.cc | 2 +- - src/x64/lithium-x64.h | 6 +++ + src/x64/full-codegen-x64.cc | 28 +++++++++------- + src/x64/lithium-codegen-x64.cc | 9 +++-- + src/x64/lithium-x64.cc | 4 +- + src/x64/lithium-x64.h | 12 +++++++ src/x64/macro-assembler-x64.h | 5 +++ - 45 files changed, 455 insertions(+), 109 deletions(-) + 47 files changed, 490 insertions(+), 117 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 +76,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 +90,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 +100,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 +110,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 +120,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 +128,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 +137,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 7d54252..2d3d97a 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 +150,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 +160,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 +188,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 +209,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 +218,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() { +@@ -4337,6 +4347,30 @@ v8::Local<v8::Context> Context::GetCalling() { } @@ -251,10 +254,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 cb3bc88..f5be938 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 +269,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 497a295..b8e3f30 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 +287,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); +@@ -1193,9 +1194,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. +@@ -1280,10 +1281,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; + } +@@ -1920,7 +1921,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()))); +@@ -2220,10 +2221,13 @@ void FullCodeGenerator::EmitResolvePossiblyDirectEval(ResolveEvalFlag flag, + FLAG_harmony_scoping ? kStrictMode : strict_mode_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 +337,41 @@ index 871b453..a69f10d 100644 } -@@ -2263,9 +2267,9 @@ void FullCodeGenerator::VisitCall(Call* expr) { +@@ -2296,9 +2300,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; +@@ -3711,7 +3715,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); +@@ -3997,7 +4001,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 5197842..943bc82 100644 --- a/src/arm/lithium-arm.cc +++ b/src/arm/lithium-arm.cc -@@ -1195,7 +1195,7 @@ LInstruction* LChunkBuilder::DoOuterContext(HOuterContext* instr) { +@@ -1128,7 +1128,7 @@ LInstruction* LChunkBuilder::DoOuterContext(HOuterContext* instr) { LInstruction* LChunkBuilder::DoGlobalObject(HGlobalObject* instr) { LOperand* context = UseRegisterAtStart(instr->value()); @@ -364,11 +380,20 @@ index 3f1d15b..8406a96 100644 } +@@ -1198,7 +1198,7 @@ LInstruction* LChunkBuilder::DoCallNamed(HCallNamed* instr) { + + LInstruction* LChunkBuilder::DoCallGlobal(HCallGlobal* instr) { + argument_count_ -= instr->argument_count(); +- return MarkAsCall(DefineFixed(new LCallGlobal, r0), instr); ++ return MarkAsCall(DefineFixed(new LCallGlobal(instr->qml_global()), r0), instr); + } + + diff --git a/src/arm/lithium-arm.h b/src/arm/lithium-arm.h -index 6da7c86..10b901f 100644 +index 5733bd0..a7e1704 100644 --- a/src/arm/lithium-arm.h +++ b/src/arm/lithium-arm.h -@@ -1378,13 +1378,17 @@ class LOuterContext: public LTemplateInstruction<1, 1, 0> { +@@ -1303,13 +1303,17 @@ class LOuterContext: public LTemplateInstruction<1, 1, 0> { class LGlobalObject: public LTemplateInstruction<1, 1, 0> { public: @@ -387,11 +412,28 @@ index 6da7c86..10b901f 100644 }; +@@ -1396,10 +1400,16 @@ class LCallGlobal: public LTemplateInstruction<1, 0, 0> { + DECLARE_CONCRETE_INSTRUCTION(CallGlobal, "call-global") + DECLARE_HYDROGEN_ACCESSOR(CallGlobal) + ++ explicit LCallGlobal(bool qml_global) : qml_global_(qml_global) {} ++ + virtual void PrintDataTo(StringStream* stream); + + Handle<String> name() const {return hydrogen()->name(); } + int arity() const { return hydrogen()->argument_count() - 1; } ++ ++ bool qml_global() { return qml_global_; } ++ private: ++ bool qml_global_; + }; + + diff --git a/src/arm/lithium-codegen-arm.cc b/src/arm/lithium-codegen-arm.cc -index 4912449..db114ea 100644 +index 4cf7df4..2e1e6fa 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,21 +448,30 @@ 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); +@@ -2826,7 +2827,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)); } +@@ -3280,7 +3281,7 @@ void LCodeGen::DoCallGlobal(LCallGlobal* instr) { + ASSERT(ToRegister(instr->result()).is(r0)); + + int arity = instr->arity(); +- RelocInfo::Mode mode = RelocInfo::CODE_TARGET_CONTEXT; ++ RelocInfo::Mode mode = instr->qml_global()?RelocInfo::CODE_TARGET:RelocInfo::CODE_TARGET_CONTEXT; + Handle<Code> ic = + isolate()->stub_cache()->ComputeCallInitialize(arity, mode); + __ mov(r2, Operand(instr->name())); diff --git a/src/arm/macro-assembler-arm.h b/src/arm/macro-assembler-arm.h -index ab5efb0..d40cdbc 100644 +index 90c4b37..5947e6a 100644 --- a/src/arm/macro-assembler-arm.h +++ b/src/arm/macro-assembler-arm.h -@@ -1056,6 +1056,11 @@ static inline MemOperand GlobalObjectOperand() { +@@ -1326,6 +1326,11 @@ static inline MemOperand GlobalObjectOperand() { } @@ -433,10 +484,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 f8b460d..217c71f 100644 --- a/src/ast-inl.h +++ b/src/ast-inl.h -@@ -106,6 +106,11 @@ bool FunctionLiteral::strict_mode() const { +@@ -126,6 +126,11 @@ StrictModeFlag FunctionLiteral::strict_mode_flag() const { } @@ -448,36 +499,52 @@ index d80684a..adc5a1f 100644 } } // namespace v8::internal #endif // V8_AST_INL_H_ +diff --git a/src/ast.cc b/src/ast.cc +index 9e34bc0..0dc3c1c 100644 +--- a/src/ast.cc ++++ b/src/ast.cc +@@ -764,6 +764,11 @@ void Call::RecordTypeFeedback(TypeFeedbackOracle* oracle, + is_monomorphic_ = oracle->CallIsMonomorphic(this); + Property* property = expression()->AsProperty(); + if (property == NULL) { ++ if (VariableProxy *proxy = expression()->AsVariableProxy()) { ++ if (proxy->var()->is_qml_global()) ++ return; ++ } ++ + // Function call. Specialize for monomorphic calls. + if (is_monomorphic_) target_ = oracle->GetCallTarget(this); + } else { diff --git a/src/ast.h b/src/ast.h -index 65a25a9..f790dc0 100644 +index 3de00ef..8920b50 100644 --- a/src/ast.h +++ b/src/ast.h -@@ -1712,6 +1712,7 @@ class FunctionLiteral: public Expression { - int end_position() const { return end_position_; } - bool is_expression() const { return is_expression_; } - bool strict_mode() const; +@@ -1653,6 +1653,7 @@ class FunctionLiteral: public Expression { + bool is_anonymous() const { return is_anonymous_; } + bool strict_mode() const { return strict_mode_flag() == kStrictMode; } + StrictModeFlag strict_mode_flag() 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 fc7000b..4380764 100644 --- a/src/code-stubs.h +++ b/src/code-stubs.h -@@ -303,7 +303,7 @@ class FastNewContextStub : public CodeStub { +@@ -326,7 +326,7 @@ class FastNewContextStub : public CodeStub { static const int kMaximumSlots = 64; explicit FastNewContextStub(int slots) : slots_(slots) { -- ASSERT(slots_ > 0 && slots <= kMaximumSlots); +- ASSERT(slots_ > 0 && slots_ <= kMaximumSlots); + ASSERT(slots_ >= 0 && slots <= kMaximumSlots); } void Generate(MacroAssembler* masm); diff --git a/src/compiler.cc b/src/compiler.cc -index 86d5de3..d2191b9 100755 +index 88db467..4902e72 100644 --- a/src/compiler.cc +++ b/src/compiler.cc -@@ -462,7 +462,8 @@ Handle<SharedFunctionInfo> Compiler::Compile(Handle<String> source, +@@ -447,7 +447,8 @@ Handle<SharedFunctionInfo> Compiler::Compile(Handle<String> source, v8::Extension* extension, ScriptDataImpl* input_pre_data, Handle<Object> script_data, @@ -487,15 +554,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, +@@ -515,6 +516,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, + compilation_cache->PutScript(source, result); +@@ -534,7 +536,8 @@ Handle<SharedFunctionInfo> Compiler::Compile(Handle<String> source, Handle<SharedFunctionInfo> Compiler::CompileEval(Handle<String> source, Handle<Context> context, bool is_global, @@ -505,17 +572,17 @@ 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, - CompilationInfo info(script); +@@ -559,6 +562,7 @@ Handle<SharedFunctionInfo> Compiler::CompileEval(Handle<String> source, info.MarkAsEval(); if (is_global) info.MarkAsGlobal(); + info.SetStrictModeFlag(strict_mode); + if (qml_mode) info.MarkAsQmlMode(); - if (strict_mode == kStrictMode) info.MarkAsStrictMode(); info.SetCallingContext(context); result = MakeFunctionInfo(&info); -@@ -610,6 +614,12 @@ bool Compiler::CompileLazy(CompilationInfo* info) { - info->MarkAsStrictMode(); - } + if (!result.is_null()) { +@@ -606,6 +610,12 @@ bool Compiler::CompileLazy(CompilationInfo* info) { + info->SetStrictModeFlag(strict_mode); + shared->set_strict_mode_flag(strict_mode); + // After parsing we know function's qml mode. Remember it. + if (info->function()->qml_mode()) { @@ -526,76 +593,63 @@ 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, +@@ -751,6 +761,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_strict_mode_flag(lit->strict_mode_flag()); + 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 bedf5ee..054e3b9 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; } +@@ -57,6 +57,7 @@ class CompilationInfo BASE_EMBEDDED { + return StrictModeFlagField::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_; } -@@ -83,6 +84,9 @@ class CompilationInfo BASE_EMBEDDED { +@@ -85,6 +86,9 @@ class CompilationInfo BASE_EMBEDDED { ASSERT(is_lazy()); flags_ |= IsInLoop::encode(true); } + void MarkAsQmlMode() { + flags_ |= IsQmlMode::encode(true); + } - void MarkAsAllowingNativesSyntax() { - flags_ |= IsNativesSyntaxAllowed::encode(true); + void MarkAsNative() { + flags_ |= IsNative::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(); -+ } +@@ -192,6 +196,9 @@ class CompilationInfo BASE_EMBEDDED { + ASSERT(strict_mode_flag() == kNonStrictMode); + SetStrictModeFlag(shared_info_->strict_mode_flag()); } ++ 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? - class IsNativesSyntaxAllowed: public BitField<bool, 5, 1> {}; + void SetMode(Mode mode) { +@@ -218,7 +225,8 @@ class CompilationInfo BASE_EMBEDDED { + // If compiling for debugging produce just full code matching the + // initial mode setting. + class IsCompilingForDebugging: public BitField<bool, 8, 1> {}; +- + // Qml mode -+ class IsQmlMode: public BitField<bool, 6, 1> {}; ++ class IsQmlMode: public BitField<bool, 9, 1> {}; unsigned flags_; -@@ -252,13 +264,15 @@ class Compiler : public AllStatic { +@@ -283,13 +291,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 +662,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 b25ffac..3129af0 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 +675,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 +684,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() || +@@ -228,6 +236,33 @@ Handle<Object> Context::Lookup(Handle<String> name, } } while (follow_context_chain); @@ -664,22 +718,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 7021ff8..c3cfeee 100644 --- a/src/contexts.h +++ b/src/contexts.h -@@ -182,6 +182,7 @@ class Context: public FixedArray { - FCONTEXT_INDEX, - PREVIOUS_INDEX, +@@ -218,6 +218,7 @@ class Context: public FixedArray { + // (with contexts), or the variable name (catch contexts), the serialized + // scope info (block contexts). EXTENSION_INDEX, + QML_GLOBAL_INDEX, GLOBAL_INDEX, MIN_CONTEXT_SLOTS, -@@ -273,6 +274,9 @@ class Context: public FixedArray { +@@ -321,6 +322,9 @@ class Context: public FixedArray { } void set_global(GlobalObject* global) { set(GLOBAL_INDEX, global); } @@ -690,71 +744,82 @@ 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 29955fa..4261ac2 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 is_construct, Handle<Object> receiver, int argc, - Object*** args, + Handle<Object> args[], - bool* has_pending_exception) { + bool* has_pending_exception, + Handle<Object> qml) { - Isolate* isolate = func->GetIsolate(); + Isolate* isolate = function->GetIsolate(); // Entering JavaScript. -@@ -107,6 +108,12 @@ static Handle<Object> Invoke(bool construct, +@@ -102,6 +103,12 @@ static Handle<Object> Invoke(bool is_construct, // make the current one is indeed a global object. - ASSERT(func->context()->global()->IsGlobalObject()); + ASSERT(function->context()->global()->IsGlobalObject()); + Handle<JSObject> oldqml; + if (!qml.is_null()) { -+ oldqml = Handle<JSObject>(func->context()->qml_global()); -+ func->context()->set_qml_global(JSObject::cast(*qml)); ++ oldqml = Handle<JSObject>(function->context()->qml_global()); ++ function->context()->set_qml_global(JSObject::cast(*qml)); + } + { // 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, - receiver_pointer, argc, args); +@@ -118,6 +125,9 @@ static Handle<Object> Invoke(bool is_construct, + CALL_GENERATED_CODE(stub_entry, function_entry, func, recv, argc, argv); } + if (!qml.is_null()) -+ func->context()->set_qml_global(*oldqml); ++ function->context()->set_qml_global(*oldqml); + #ifdef DEBUG value->Verify(); #endif -@@ -150,14 +160,24 @@ Handle<Object> Execution::Call(Handle<JSFunction> func, +@@ -146,7 +156,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>()); + Handle<Object> argv[], + bool* pending_exception, +- bool convert_receiver) { ++ bool convert_receiver) ++{ ++ return Call(callable, receiver, argc, argv, 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, ++ Handle<Object> argv[], + bool* pending_exception, ++ bool convert_receiver, + Handle<Object> qml) { -+ return Invoke(false, func, receiver, argc, args, pending_exception, qml); + *pending_exception = false; + + if (!callable->IsJSFunction()) { +@@ -170,7 +191,7 @@ Handle<Object> Execution::Call(Handle<Object> callable, + if (*pending_exception) return callable; + } + +- return Invoke(false, func, receiver, argc, argv, pending_exception); ++ return Invoke(false, func, receiver, argc, argv, pending_exception, qml); } - Handle<Object> Execution::New(Handle<JSFunction> func, int argc, - Object*** args, bool* pending_exception) { - return Invoke(true, func, Isolate::Current()->global(), argc, args, +@@ -179,7 +200,7 @@ Handle<Object> Execution::New(Handle<JSFunction> func, + Handle<Object> argv[], + bool* pending_exception) { + return Invoke(true, func, Isolate::Current()->global(), argc, argv, - pending_exception); + pending_exception, Handle<Object>()); } -@@ -175,7 +195,7 @@ Handle<Object> Execution::TryCall(Handle<JSFunction> func, - catcher.SetCaptureMessage(false); +@@ -198,7 +219,7 @@ Handle<Object> Execution::TryCall(Handle<JSFunction> func, + *caught_exception = false; Handle<Object> result = Invoke(false, func, receiver, argc, args, - caught_exception); @@ -763,36 +828,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 f2d17d0..532e5d8 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, ++ Handle<Object> argv[], + 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 27c509f..f099d25 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) { +@@ -513,7 +513,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( +@@ -537,6 +537,7 @@ void FullCodeGenerator::VisitDeclarations( } array->set(j++, *function); } @@ -801,42 +868,74 @@ 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 9132502..78e6089 100644 --- a/src/full-codegen.h +++ b/src/full-codegen.h -@@ -505,6 +505,7 @@ class FullCodeGenerator: public AstVisitor { +@@ -583,6 +583,7 @@ class FullCodeGenerator: public AstVisitor { StrictModeFlag strict_mode_flag() { - return is_strict_mode() ? kStrictMode : kNonStrictMode; + return function()->strict_mode_flag(); } + 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 53a0f27..881a876 100644 --- a/src/heap.cc +++ b/src/heap.cc -@@ -3795,6 +3795,7 @@ MaybeObject* Heap::AllocateFunctionContext(int length, JSFunction* function) { - context->set_previous(NULL); +@@ -4355,6 +4355,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; + } + +@@ -4375,6 +4376,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; + } +@@ -4393,6 +4395,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; + } + +@@ -4411,6 +4414,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.cc b/src/hydrogen-instructions.cc +index 6f46509..ac9728c 100644 +--- a/src/hydrogen-instructions.cc ++++ b/src/hydrogen-instructions.cc +@@ -655,6 +655,11 @@ void HCallNamed::PrintDataTo(StringStream* stream) { + } + + ++void HGlobalObject::PrintDataTo(StringStream* stream) { ++ stream->Add("qml_global: %s ", qml_global()?"true":"false"); ++ HUnaryOperation::PrintDataTo(stream); ++} ++ + void HCallGlobal::PrintDataTo(StringStream* stream) { + stream->Add("%o ", *name()); + HUnaryCall::PrintDataTo(stream); diff --git a/src/hydrogen-instructions.h b/src/hydrogen-instructions.h -index a623775..52455bc 100644 +index 65fc4df..c29d781 100644 --- a/src/hydrogen-instructions.h +++ b/src/hydrogen-instructions.h -@@ -1148,7 +1148,7 @@ class HOuterContext: public HUnaryOperation { +@@ -1410,19 +1410,27 @@ class HOuterContext: public HUnaryOperation { class HGlobalObject: public HUnaryOperation { public: @@ -845,7 +944,12 @@ index a623775..52455bc 100644 set_representation(Representation::Tagged()); SetFlag(kUseGVN); } -@@ -1159,8 +1159,14 @@ class HGlobalObject: public HUnaryOperation { + ++ virtual void PrintDataTo(StringStream* stream); ++ + DECLARE_CONCRETE_INSTRUCTION(GlobalObject) + + virtual Representation RequiredInputRepresentation(int index) { return Representation::Tagged(); } @@ -860,61 +964,88 @@ index a623775..52455bc 100644 }; -@@ -1177,7 +1183,7 @@ class HGlobalReceiver: public HUnaryOperation { - virtual Representation RequiredInputRepresentation(int index) const { +@@ -1601,7 +1609,7 @@ class HCallFunction: public HUnaryCall { + class HCallGlobal: public HUnaryCall { + public: + HCallGlobal(HValue* context, Handle<String> name, int argument_count) +- : HUnaryCall(context, argument_count), name_(name) { ++ : HUnaryCall(context, argument_count), name_(name), qml_global_(false) { + } + + virtual void PrintDataTo(StringStream* stream); +@@ -1613,10 +1621,14 @@ class HCallGlobal: public HUnaryCall { return Representation::Tagged(); } -- -+ - protected: - virtual bool DataEquals(HValue* other) { return true; } + ++ bool qml_global() { return qml_global_; } ++ void set_qml_global(bool v) { qml_global_ = v; } ++ + DECLARE_CONCRETE_INSTRUCTION(CallGlobal) + + private: + Handle<String> name_; ++ bool qml_global_; }; + + diff --git a/src/hydrogen.cc b/src/hydrogen.cc -index 73ea97d..d17e304 100644 +index 3a4d172..0a7fad1 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); +@@ -3185,6 +3185,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, +@@ -3644,6 +3645,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, +@@ -5106,11 +5108,13 @@ void HGraphBuilder::VisitCall(Call* expr) { + } else { + HValue* context = environment()->LookupContext(); + HGlobalObject* receiver = new(zone()) HGlobalObject(context); ++ if (var->is_qml_global()) receiver->set_qml_global(true); + AddInstruction(receiver); + PushAndAdd(new(zone()) HPushArgument(receiver)); + CHECK_ALIVE(VisitArgumentList(expr->arguments())); + + call = new(zone()) HCallGlobal(context, var->name(), argument_count); ++ if (var->is_qml_global()) static_cast<HCallGlobal*>(call)->set_qml_global(true); + Drop(argument_count); + } + diff --git a/src/ia32/code-stubs-ia32.cc b/src/ia32/code-stubs-ia32.cc -index 5d32095..afa599e 100644 +index 37b519a..8a94a06 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))); +@@ -144,6 +144,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 25588c8..9cee4a3 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 +1057,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); +@@ -1179,10 +1180,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); +@@ -1263,10 +1264,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; + } +@@ -1920,7 +1921,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()))); +@@ -2235,9 +2236,12 @@ void FullCodeGenerator::EmitResolvePossiblyDirectEval(ResolveEvalFlag flag, + FLAG_harmony_scoping ? kStrictMode : strict_mode_flag(); + __ push(Immediate(Smi::FromInt(strict_mode))); + // Push the qml mode flag + __ push(Immediate(Smi::FromInt(is_qml_mode()))); @@ -981,22 +1107,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()) { +@@ -2308,9 +2312,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). +@@ -3777,7 +3781,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); +@@ -4085,7 +4089,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 d4cbbce..b381227 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 +1156,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); +@@ -2661,7 +2662,7 @@ void LCodeGen::DoOuterContext(LOuterContext* instr) { void LCodeGen::DoGlobalObject(LGlobalObject* instr) { Register context = ToRegister(instr->context()); Register result = ToRegister(instr->result()); @@ -1021,11 +1166,20 @@ index 0f96f78..c1da075 100644 } +@@ -3131,7 +3132,7 @@ void LCodeGen::DoCallGlobal(LCallGlobal* instr) { + ASSERT(ToRegister(instr->result()).is(eax)); + + int arity = instr->arity(); +- RelocInfo::Mode mode = RelocInfo::CODE_TARGET_CONTEXT; ++ RelocInfo::Mode mode = instr->qml_global()?RelocInfo::CODE_TARGET:RelocInfo::CODE_TARGET_CONTEXT; + Handle<Code> ic = + isolate()->stub_cache()->ComputeCallInitialize(arity, mode); + __ mov(ecx, instr->name()); diff --git a/src/ia32/lithium-ia32.cc b/src/ia32/lithium-ia32.cc -index 9ccd189..8e98b73 100644 +index 626f899..d09d55f 100644 --- a/src/ia32/lithium-ia32.cc +++ b/src/ia32/lithium-ia32.cc -@@ -1205,7 +1205,7 @@ LInstruction* LChunkBuilder::DoOuterContext(HOuterContext* instr) { +@@ -1144,7 +1144,7 @@ LInstruction* LChunkBuilder::DoOuterContext(HOuterContext* instr) { LInstruction* LChunkBuilder::DoGlobalObject(HGlobalObject* instr) { LOperand* context = UseRegisterAtStart(instr->value()); @@ -1034,11 +1188,20 @@ index 9ccd189..8e98b73 100644 } +@@ -1228,7 +1228,7 @@ LInstruction* LChunkBuilder::DoCallNamed(HCallNamed* instr) { + LInstruction* LChunkBuilder::DoCallGlobal(HCallGlobal* instr) { + LOperand* context = UseFixed(instr->context(), esi); + argument_count_ -= instr->argument_count(); +- LCallGlobal* result = new LCallGlobal(context); ++ LCallGlobal* result = new LCallGlobal(context, instr->qml_global()); + return MarkAsCall(DefineFixed(result, eax), instr); + } + diff --git a/src/ia32/lithium-ia32.h b/src/ia32/lithium-ia32.h -index 9ace8f8..95ed001 100644 +index 5f23afa..22541c8 100644 --- a/src/ia32/lithium-ia32.h +++ b/src/ia32/lithium-ia32.h -@@ -1416,13 +1416,17 @@ class LOuterContext: public LTemplateInstruction<1, 1, 0> { +@@ -1338,13 +1338,17 @@ class LOuterContext: public LTemplateInstruction<1, 1, 0> { class LGlobalObject: public LTemplateInstruction<1, 1, 0> { public: @@ -1057,83 +1220,90 @@ index 9ace8f8..95ed001 100644 }; +@@ -1443,7 +1447,7 @@ class LCallFunction: public LTemplateInstruction<1, 1, 0> { + + class LCallGlobal: public LTemplateInstruction<1, 1, 0> { + public: +- explicit LCallGlobal(LOperand* context) { ++ explicit LCallGlobal(LOperand* context, bool qml_global) : qml_global_(qml_global) { + inputs_[0] = context; + } + +@@ -1455,6 +1459,10 @@ class LCallGlobal: public LTemplateInstruction<1, 1, 0> { + LOperand* context() { return inputs_[0]; } + Handle<String> name() const {return hydrogen()->name(); } + int arity() const { return hydrogen()->argument_count() - 1; } ++ ++ bool qml_global() { return qml_global_; } ++ private: ++ bool qml_global_; + }; + + diff --git a/src/ia32/macro-assembler-ia32.h b/src/ia32/macro-assembler-ia32.h -index b986264..f8479ae 100644 +index 8528c55..de3c3a0 100644 --- a/src/ia32/macro-assembler-ia32.h +++ b/src/ia32/macro-assembler-ia32.h -@@ -778,6 +778,11 @@ static inline Operand GlobalObjectOperand() { +@@ -935,6 +935,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 6a80c9c..2e83fb7 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) - +@@ -3535,6 +3535,8 @@ void SharedFunctionInfo::set_strict_mode_flag(StrictModeFlag strict_mode_flag) { + + BOOL_GETTER(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 c38d461..73e7f8b 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); - -+ // Indicates whether the function is a qml mode function -+ inline bool qml_mode(); -+ inline void set_qml_mode(bool value); -+ - // 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; +@@ -4929,6 +4929,9 @@ class SharedFunctionInfo: public HeapObject { + inline StrictModeFlag strict_mode_flag(); + inline void set_strict_mode_flag(StrictModeFlag strict_mode_flag); - private: - #if V8_HOST_ARCH_32_BIT ++ // Indicates whether the function is a qml mode function. ++ DECL_BOOLEAN_ACCESSORS(qml_mode) ++ + // False if the function definitely does not allocate an arguments object. + DECL_BOOLEAN_ACCESSORS(uses_arguments) + +@@ -5150,6 +5153,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 37204c9..357d340 100644 --- a/src/parser.cc +++ b/src/parser.cc -@@ -593,7 +593,8 @@ Parser::Parser(Handle<Script> script, +@@ -607,7 +607,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, +@@ -623,11 +624,11 @@ FunctionLiteral* Parser::ParseProgram(Handle<String> source, ExternalTwoByteStringUC16CharacterStream stream( Handle<ExternalTwoByteString>::cast(source), 0, source->length()); scanner_.Initialize(&stream); @@ -1147,35 +1317,36 @@ index a84ec6f..7f5c361 100644 } } -@@ -621,6 +622,7 @@ FunctionLiteral* Parser::ParseProgram(Handle<String> source, +@@ -635,6 +636,7 @@ FunctionLiteral* Parser::ParseProgram(Handle<String> source, FunctionLiteral* Parser::DoParseProgram(Handle<String> source, bool in_global_context, StrictModeFlag strict_mode, + bool qml_mode, ZoneScope* zone_scope) { + ASSERT(top_scope_ == NULL); ASSERT(target_stack_ == NULL); - if (pre_data_ != NULL) pre_data_->Initialize(); -@@ -641,6 +643,9 @@ FunctionLiteral* Parser::DoParseProgram(Handle<String> source, - if (strict_mode == kStrictMode) { - top_scope_->EnableStrictMode(); - } +@@ -654,6 +656,9 @@ FunctionLiteral* Parser::DoParseProgram(Handle<String> source, + LexicalScope lexical_scope(this, scope, isolate()); + ASSERT(top_scope_->strict_mode_flag() == kNonStrictMode); + top_scope_->SetStrictModeFlag(strict_mode); + 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, - if (shared_info->strict_mode()) { - top_scope_->EnableStrictMode(); - } +@@ -747,6 +752,10 @@ FunctionLiteral* Parser::ParseLazy(CompilationInfo* info, + scope->strict_mode_flag() == info->strict_mode_flag()); + ASSERT(info->strict_mode_flag() == shared_info->strict_mode_flag()); + scope->SetStrictModeFlag(shared_info->strict_mode_flag()); + if (shared_info->qml_mode()) { + 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() + ? FunctionLiteral::ANONYMOUS_EXPRESSION +@@ -1856,6 +1865,11 @@ Block* Parser::ParseVariableDeclarations( arguments->Add(value); value = NULL; // zap the value to avoid the unnecessary assignment @@ -1187,9 +1358,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)); +@@ -1872,6 +1886,11 @@ Block* Parser::ParseVariableDeclarations( + StrictModeFlag flag = initialization_scope->strict_mode_flag(); + arguments->Add(NewNumberLiteral(flag)); + int qml_mode = 0; + if (top_scope_->is_qml_mode() && !Isolate::Current()->global()->HasProperty(*name)) @@ -1199,31 +1370,31 @@ 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) { +@@ -5418,7 +5437,8 @@ bool ParserApi::Parse(CompilationInfo* info) { Handle<String> source = Handle<String>(String::cast(script->source())); result = parser.ParseProgram(source, info->is_global(), -- info->StrictMode()); -+ info->StrictMode(), +- info->strict_mode_flag()); ++ info->strict_mode_flag(), + info->is_qml_mode()); } } - + info->SetFunction(result); diff --git a/src/parser.h b/src/parser.h -index 64f1303..4d45e45 100644 +index eaae6f7..a60951d 100644 --- a/src/parser.h +++ b/src/parser.h -@@ -431,7 +431,8 @@ class Parser { +@@ -430,7 +430,8 @@ class Parser { // Returns NULL if parsing failed. FunctionLiteral* ParseProgram(Handle<String> source, bool in_global_context, - StrictModeFlag strict_mode); + StrictModeFlag strict_mode, -+ bool qml_mode); ++ bool qml_mode = false); FunctionLiteral* ParseLazy(CompilationInfo* info); -@@ -464,6 +465,7 @@ class Parser { +@@ -476,6 +477,7 @@ class Parser { FunctionLiteral* DoParseProgram(Handle<String> source, bool in_global_context, StrictModeFlag strict_mode, @@ -1232,10 +1403,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 +1417,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 0e256c1..5746c20 100644 --- a/src/runtime.cc +++ b/src/runtime.cc -@@ -1065,8 +1065,6 @@ static Failure* ThrowRedeclarationError(Isolate* isolate, +@@ -1307,19 +1307,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 +1447,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) { +@@ -1506,19 +1510,24 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeVarGlobal) { NoHandleAllocation nha; // args[0] == name // args[1] == strict_mode @@ -1301,8 +1465,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 +1476,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); +@@ -1546,7 +1555,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); +@@ -1556,9 +1565,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 +1497,7 @@ index 660352c..c13f92d 100644 } return isolate->heap()->undefined_value(); } -@@ -1411,12 +1420,15 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeConstGlobal) { +@@ -1568,12 +1577,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 +1515,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. +@@ -1597,7 +1609,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) { +@@ -9386,7 +9398,8 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_CompileString) { Handle<SharedFunctionInfo> shared = Compiler::CompileEval(source, context, true, @@ -1389,26 +1534,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) { +@@ -9399,7 +9412,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()); + +@@ -9417,7 +9431,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, +@@ -9427,7 +9442,7 @@ static ObjectPair CompileGlobalEval(Isolate* isolate, RUNTIME_FUNCTION(ObjectPair, Runtime_ResolvePossiblyDirectEval) { @@ -1417,7 +1563,7 @@ index 660352c..c13f92d 100644 HandleScope scope(isolate); Handle<Object> callee = args.at<Object>(0); -@@ -8257,16 +8272,18 @@ RUNTIME_FUNCTION(ObjectPair, Runtime_ResolvePossiblyDirectEval) { +@@ -9490,15 +9505,17 @@ RUNTIME_FUNCTION(ObjectPair, Runtime_ResolvePossiblyDirectEval) { } ASSERT(args[3]->IsSmi()); @@ -1425,9 +1571,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 +1583,7 @@ index 660352c..c13f92d 100644 HandleScope scope(isolate); Handle<Object> callee = args.at<Object>(0); -@@ -8280,11 +8297,13 @@ RUNTIME_FUNCTION(ObjectPair, Runtime_ResolvePossiblyDirectEvalNoLookup) { +@@ -9511,10 +9528,12 @@ RUNTIME_FUNCTION(ObjectPair, Runtime_ResolvePossiblyDirectEvalNoLookup) { } ASSERT(args[3]->IsSmi()); @@ -1446,14 +1591,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) { +@@ -12034,6 +12053,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 +1605,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) { +@@ -12107,7 +12127,8 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugEvaluate) { Compiler::CompileEval(function_source, context, context->IsGlobalContext(), @@ -1471,17 +1615,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, +@@ -12117,7 +12138,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, +@@ -12198,7 +12220,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 +1635,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 67fc628..aada06d 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 +1649,9 @@ index bf1ba68..5e97173 100644 \ F(SetProperty, -1 /* 4 or 5 */, 1) \ F(DefineOrRedefineDataProperty, 4, 1) \ -@@ -296,8 +296,8 @@ namespace internal { +@@ -336,8 +336,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,102 +1661,112 @@ index bf1ba68..5e97173 100644 F(OptimizeObjectForAddingMultipleProperties, 2, 1) \ \ diff --git a/src/scopes.cc b/src/scopes.cc -index 8df93c5..b5d7ff3 100644 +index 3167c4d..6503d07 100644 --- a/src/scopes.cc +++ b/src/scopes.cc -@@ -198,6 +198,7 @@ void Scope::SetDefaults(Type type, - scope_calls_eval_ = false; +@@ -35,6 +35,8 @@ + + #include "allocation-inl.h" + ++#include "debug.h" ++ + namespace v8 { + namespace internal { + +@@ -202,6 +204,7 @@ void Scope::SetDefaults(ScopeType type, // Inherit the strict mode from the parent scope. - strict_mode_ = (outer_scope != NULL) && outer_scope->strict_mode_; + strict_mode_flag_ = (outer_scope != NULL) + ? outer_scope->strict_mode_flag_ : kNonStrictMode; + 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, - ASSERT(global_scope != NULL); - var = global_scope->DeclareGlobal(proxy->name()); - + force_eager_compilation_ = false; +@@ -907,6 +910,26 @@ void Scope::ResolveVariable(Scope* global_scope, + // by 'eval' introduced variable bindings. + if (var->is_global()) { + var = NonLocal(proxy->name(), DYNAMIC_GLOBAL); ++ + if (qml_mode_) { -+ Handle<GlobalObject> global = Isolate::Current()->global(); ++ Handle<GlobalObject> global = isolate_->global(); + +#ifdef ENABLE_DEBUGGER_SUPPORT -+ if (Isolate::Current()->debug()->IsLoaded() && Isolate::Current()->debug()->InDebugger()) { ++ if (isolate_->debug()->IsLoaded() && isolate_->debug()->InDebugger()) { + //Get the context before the debugger was entered. -+ SaveContext *save = Isolate::Current()->save_context(); -+ while (save != NULL && *save->context() == *Isolate::Current()->debug()->debug_context()) ++ SaveContext *save = isolate_->save_context(); ++ while (save != NULL && *save->context() == *isolate_->debug()->debug_context()) + save = save->prev(); + + global = Handle<GlobalObject>(save->context()->global()); + } +#endif + -+ if (!global->HasProperty(*(proxy->name()))) { ++ if (qml_mode_ && !global->HasProperty(*(proxy->name()))) { + var->set_is_qml_global(true); + } + } + - } 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, - if (context->GlobalIfNotShadowedByEval(proxy->name())) { - var = NonLocal(proxy->name(), Variable::DYNAMIC_GLOBAL); - -+ if (qml_mode_) { -+ Handle<GlobalObject> global = Isolate::Current()->global(); + } else { + Variable* invalidated = var; + var = NonLocal(proxy->name(), DYNAMIC_LOCAL); +@@ -918,12 +941,52 @@ void Scope::ResolveVariable(Scope* global_scope, + // No binding has been found. Declare a variable in global scope. + ASSERT(global_scope != NULL); + var = global_scope->DeclareGlobal(proxy->name()); ++ ++ if (qml_mode_) { ++ Handle<GlobalObject> global = isolate_->global(); + +#ifdef ENABLE_DEBUGGER_SUPPORT -+ if (Isolate::Current()->debug()->IsLoaded() && Isolate::Current()->debug()->InDebugger()) { -+ //Get the context before the debugger was entered. -+ SaveContext *save = Isolate::Current()->save_context(); -+ while (save != NULL && *save->context() == *Isolate::Current()->debug()->debug_context()) -+ save = save->prev(); -+ -+ global = Handle<GlobalObject>(save->context()->global()); -+ } ++ if (isolate_->debug()->IsLoaded() && isolate_->debug()->InDebugger()) { ++ //Get the context before the debugger was entered. ++ SaveContext *save = isolate_->save_context(); ++ while (save != NULL && *save->context() == *isolate_->debug()->debug_context()) ++ save = save->prev(); ++ ++ global = Handle<GlobalObject>(save->context()->global()); ++ } +#endif + -+ if (qml_mode_ && !global->HasProperty(*(proxy->name()))) { -+ var->set_is_qml_global(true); -+ } -+ } ++ if (!global->HasProperty(*(proxy->name()))) { ++ var->set_is_qml_global(true); ++ } ++ } + - } else { - var = NonLocal(proxy->name(), Variable::DYNAMIC); - } -@@ -827,6 +866,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); + break; + + case UNBOUND_EVAL_SHADOWED: + // No binding has been found. But some scope makes a + // non-strict 'eval' call. + var = NonLocal(proxy->name(), DYNAMIC_GLOBAL); + -+ if (qml_mode_) { -+ Handle<GlobalObject> global = Isolate::Current()->global(); ++ if (qml_mode_) { ++ Handle<GlobalObject> global = isolate_->global(); + +#ifdef ENABLE_DEBUGGER_SUPPORT -+ if (Isolate::Current()->debug()->IsLoaded() && Isolate::Current()->debug()->InDebugger()) { -+ //Get the context before the debugger was entered. -+ SaveContext *save = Isolate::Current()->save_context(); -+ while (save != NULL && *save->context() == *Isolate::Current()->debug()->debug_context()) -+ save = save->prev(); ++ if (isolate_->debug()->IsLoaded() && isolate_->debug()->InDebugger()) { ++ //Get the context before the debugger was entered. ++ SaveContext *save = isolate_->save_context(); ++ while (save != NULL && *save->context() == *isolate_->debug()->debug_context()) ++ save = save->prev(); + -+ global = Handle<GlobalObject>(save->context()->global()); -+ } ++ global = Handle<GlobalObject>(save->context()->global()); ++ } +#endif + -+ if (qml_mode_ && !global->HasProperty(*(proxy->name()))) { -+ var->set_is_qml_global(true); -+ } ++ if (qml_mode_ && !global->HasProperty(*(proxy->name()))) { ++ var->set_is_qml_global(true); + } ++ } + - } - } - } + break; + + case DYNAMIC_LOOKUP: diff --git a/src/scopes.h b/src/scopes.h -index a0e56a4..6dd3f65 100644 +index a141887..41e5f5c 100644 --- a/src/scopes.h +++ b/src/scopes.h -@@ -210,6 +210,11 @@ class Scope: public ZoneObject { - strict_mode_ = FLAG_strict_mode; +@@ -228,6 +228,11 @@ class Scope: public ZoneObject { + end_position_ = statement_pos; } + // Enable qml mode for this scope @@ -1623,28 +1777,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; } - bool is_strict_mode() const { return strict_mode_; } +@@ -242,6 +247,7 @@ class Scope: public ZoneObject { + return is_eval_scope() || is_function_scope() || is_global_scope(); + } + bool is_strict_mode() const { return strict_mode_flag() == kStrictMode; } + 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(); + } +@@ -427,6 +433,8 @@ class Scope: public ZoneObject { + // Source positions. + int start_position_; + int end_position_; ++ // This scope is a qml mode scope. ++ bool qml_mode_; // Computed via PropagateScopeInfo. - bool outer_scope_calls_eval_; + bool outer_scope_calls_non_strict_eval_; diff --git a/src/variables.cc b/src/variables.cc -index 0502722..190baf6 100644 +index d85e1b2..1887935 100644 --- a/src/variables.cc +++ b/src/variables.cc -@@ -99,7 +99,8 @@ Variable::Variable(Scope* scope, - rewrite_(NULL), +@@ -68,7 +68,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 +1809,19 @@ index 0502722..190baf6 100644 ASSERT(name->IsSymbol()); } diff --git a/src/variables.h b/src/variables.h -index b1ff0db..0b31d1a 100644 +index 8b2d869..33561b0 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; } +@@ -155,6 +155,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 { +@@ -175,6 +177,9 @@ class Variable: public ZoneObject { // Usage info. bool is_accessed_from_inner_scope_; // set by variable resolver bool is_used_; @@ -1677,14 +1832,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 f62c517..f30221f 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 +1847,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 bf640db..b1e5d35 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 +1865,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); +@@ -1155,10 +1156,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); +@@ -1240,9 +1241,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; + } +@@ -1834,7 +1835,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())); +@@ -2117,9 +2118,12 @@ void FullCodeGenerator::EmitResolvePossiblyDirectEval(ResolveEvalFlag flag, + FLAG_harmony_scoping ? kStrictMode : strict_mode_flag(); + __ Push(Smi::FromInt(strict_mode)); + // Push the qml mode flag + __ Push(Smi::FromInt(is_qml_mode())); @@ -1764,22 +1914,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. +@@ -2188,8 +2192,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; +@@ -3638,7 +3642,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); +@@ -3936,7 +3940,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 38a8c18..2a95fee 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 +1962,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); +@@ -2610,7 +2611,7 @@ void LCodeGen::DoOuterContext(LOuterContext* instr) { void LCodeGen::DoGlobalObject(LGlobalObject* instr) { Register result = ToRegister(instr->result()); @@ -1804,11 +1972,20 @@ index 202e7a2..45acbdf 100644 } +@@ -3049,7 +3050,7 @@ void LCodeGen::DoCallFunction(LCallFunction* instr) { + void LCodeGen::DoCallGlobal(LCallGlobal* instr) { + ASSERT(ToRegister(instr->result()).is(rax)); + int arity = instr->arity(); +- RelocInfo::Mode mode = RelocInfo::CODE_TARGET_CONTEXT; ++ RelocInfo::Mode mode = instr->qml_global()?RelocInfo::CODE_TARGET:RelocInfo::CODE_TARGET_CONTEXT; + Handle<Code> ic = + isolate()->stub_cache()->ComputeCallInitialize(arity, mode); + __ Move(rcx, instr->name()); diff --git a/src/x64/lithium-x64.cc b/src/x64/lithium-x64.cc -index 07ca3a5..00feeac 100644 +index 0af2ce4..9e2731f 100644 --- a/src/x64/lithium-x64.cc +++ b/src/x64/lithium-x64.cc -@@ -1194,7 +1194,7 @@ LInstruction* LChunkBuilder::DoOuterContext(HOuterContext* instr) { +@@ -1123,7 +1123,7 @@ LInstruction* LChunkBuilder::DoOuterContext(HOuterContext* instr) { LInstruction* LChunkBuilder::DoGlobalObject(HGlobalObject* instr) { @@ -1817,11 +1994,20 @@ index 07ca3a5..00feeac 100644 } +@@ -1193,7 +1193,7 @@ LInstruction* LChunkBuilder::DoCallNamed(HCallNamed* instr) { + + LInstruction* LChunkBuilder::DoCallGlobal(HCallGlobal* instr) { + argument_count_ -= instr->argument_count(); +- return MarkAsCall(DefineFixed(new LCallGlobal, rax), instr); ++ return MarkAsCall(DefineFixed(new LCallGlobal(instr->qml_global()), rax), instr); + } + + diff --git a/src/x64/lithium-x64.h b/src/x64/lithium-x64.h -index 15bb894..16f754c 100644 +index 20a6937..8f1a3d8 100644 --- a/src/x64/lithium-x64.h +++ b/src/x64/lithium-x64.h -@@ -1365,7 +1365,13 @@ class LOuterContext: public LTemplateInstruction<1, 1, 0> { +@@ -1303,7 +1303,13 @@ class LOuterContext: public LTemplateInstruction<1, 1, 0> { class LGlobalObject: public LTemplateInstruction<1, 0, 0> { public: @@ -1835,11 +2021,28 @@ index 15bb894..16f754c 100644 }; +@@ -1393,10 +1399,16 @@ class LCallGlobal: public LTemplateInstruction<1, 0, 0> { + DECLARE_CONCRETE_INSTRUCTION(CallGlobal, "call-global") + DECLARE_HYDROGEN_ACCESSOR(CallGlobal) + ++ explicit LCallGlobal(bool qml_global) : qml_global_(qml_global) {} ++ + virtual void PrintDataTo(StringStream* stream); + + Handle<String> name() const {return hydrogen()->name(); } + int arity() const { return hydrogen()->argument_count() - 1; } ++ ++ bool qml_global() { return qml_global_; } ++ private: ++ bool qml_global_; + }; + + diff --git a/src/x64/macro-assembler-x64.h b/src/x64/macro-assembler-x64.h -index 4c17720..aa284ed 100644 +index f5f81b1..5caa6cf 100644 --- a/src/x64/macro-assembler-x64.h +++ b/src/x64/macro-assembler-x64.h -@@ -1233,6 +1233,11 @@ static inline Operand GlobalObjectOperand() { +@@ -1418,6 +1418,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..ee7047e7ba 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 a321f382dd8a63ed71cd00a57d011f966a35645f 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 2d3d97a..54df40d 100644 --- a/src/api.cc +++ b/src/api.cc -@@ -3976,6 +3976,18 @@ v8::Local<v8::Object> Context::GetCallingQmlGlobal() { +@@ -4370,6 +4370,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..cd779ad94e 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 15e2b05fae59aa4ed7c0974ba296ec8893c4d7f2 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: Thu, 27 Oct 2011 13:40:00 +0100 +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 54df40d..974d702 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( + +@@ -5113,6 +5124,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 f5be938..1e1aebd 100644 --- a/src/arm/code-stubs-arm.cc +++ b/src/arm/code-stubs-arm.cc -@@ -1563,6 +1563,36 @@ void CompareStub::Generate(MacroAssembler* masm) { +@@ -1569,6 +1569,37 @@ void CompareStub::Generate(MacroAssembler* masm) { // NOTICE! This code is only reached after a smi-fast-case check, so // it is certain that at least one operand isn't a smi. @@ -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); +@@ -6615,10 +6646,18 @@ void ICCompareStub::GenerateObjects(MacroAssembler* masm) { + __ and_(r2, r1, Operand(r0)); + __ JumpIfSmi(r2, &miss); - __ CompareObjectType(r0, r2, r2, JS_OBJECT_TYPE); + __ CompareObjectType(r0, r2, r3, JS_OBJECT_TYPE); __ b(ne, &miss); - __ CompareObjectType(r1, r2, r2, JS_OBJECT_TYPE); -+ __ ldrb(r2, FieldMemOperand(r2, Map::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 8c96944..76ca69d 100644 --- a/src/factory.cc +++ b/src/factory.cc -@@ -998,6 +998,7 @@ Handle<JSFunction> Factory::CreateApiFunction( +@@ -1153,6 +1153,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( +@@ -1162,6 +1163,8 @@ Handle<JSFunction> Factory::CreateApiFunction( Smi::cast(instance_template->internal_field_count())->value(); has_external_resource = !instance_template->has_external_resource()->IsUndefined(); @@ -185,7 +190,7 @@ index d530a75..6f8c7de 100644 } int instance_size = kPointerSize * internal_field_count; -@@ -1051,6 +1054,11 @@ Handle<JSFunction> Factory::CreateApiFunction( +@@ -1206,6 +1209,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 8a94a06..e73753e 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."); - } +@@ -4020,6 +4020,39 @@ void CompareStub::Generate(MacroAssembler* masm) { + // NOTICE! This code is only reached after a smi-fast-case check, so + // it is certain that at least one operand isn't a smi. + { -+ 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. + { +@@ -6497,8 +6530,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 a073af9..36c1dfd 100644 +--- a/src/isolate.cc ++++ b/src/isolate.cc +@@ -96,6 +96,7 @@ void ThreadLocalTop::InitializeInternal() { + thread_id_ = ThreadId::Invalid(); + external_caught_exception_ = false; + failed_access_check_callback_ = NULL; ++ user_object_comparison_callback_ = NULL; + save_context_ = NULL; + catcher_ = NULL; + top_lookup_result_ = NULL; +@@ -729,6 +730,12 @@ void Isolate::SetFailedAccessCheckCallback( + thread_local_top()->failed_access_check_callback_ = callback; + } + ++ ++void Isolate::SetUserObjectComparisonCallback( ++ v8::UserObjectComparisonCallback callback) { ++ thread_local_top()->user_object_comparison_callback_ = callback; ++} ++ + + void Isolate::ReportFailedAccessCheck(JSObject* receiver, v8::AccessType type) { + if (!thread_local_top()->failed_access_check_callback_) return; diff --git a/src/isolate.h b/src/isolate.h -index 35ffcb4..8130397 100644 +index 5453bf2..9919e83 100644 --- a/src/isolate.h +++ b/src/isolate.h -@@ -267,6 +267,9 @@ class ThreadLocalTop BASE_EMBEDDED { - // Call back function to report unsafe JS accesses. - v8::FailedAccessCheckCallback failed_access_check_callback_; +@@ -258,6 +258,9 @@ class ThreadLocalTop BASE_EMBEDDED { + // Head of the list of live LookupResults. + LookupResult* top_lookup_result_; + // Call back function for user object comparisons + v8::UserObjectComparisonCallback user_object_comparison_callback_; + - private: - void InitializeInternal(); + // Whether out of memory exceptions should be ignored. + bool ignore_out_of_memory_; -@@ -699,6 +702,11 @@ class Isolate { +@@ -703,6 +706,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 2e83fb7..13d7591 100644 --- a/src/objects-inl.h +++ b/src/objects-inl.h -@@ -2552,6 +2552,19 @@ bool Map::has_external_resource() +@@ -2749,14 +2749,14 @@ bool Map::is_extensible() { + + void Map::set_attached_to_shared_function_info(bool value) { + if (value) { +- set_bit_field2(bit_field2() | (1 << kAttachedToSharedFunctionInfo)); ++ set_bit_field3(bit_field3() | (1 << kAttachedToSharedFunctionInfo)); + } else { +- set_bit_field2(bit_field2() & ~(1 << kAttachedToSharedFunctionInfo)); ++ set_bit_field3(bit_field3() & ~(1 << kAttachedToSharedFunctionInfo)); + } + } + + bool Map::attached_to_shared_function_info() { +- return ((1 << kAttachedToSharedFunctionInfo) & bit_field2()) != 0; ++ return ((1 << kAttachedToSharedFunctionInfo) & bit_field3()) != 0; + } + + +@@ -2786,6 +2786,19 @@ bool Map::has_external_resource() } +void Map::set_use_user_object_comparison(bool value) { + if (value) { -+ set_bit_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, +@@ -3334,6 +3347,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 f5b6bee..6a4eff9 100644 +--- a/src/objects.cc ++++ b/src/objects.cc +@@ -7686,8 +7686,8 @@ void SharedFunctionInfo::DetachInitialMap() { + Map* map = reinterpret_cast<Map*>(initial_map()); + + // Make the map remember to restore the link if it survives the GC. +- map->set_bit_field2( +- map->bit_field2() | (1 << Map::kAttachedToSharedFunctionInfo)); ++ map->set_bit_field3( ++ map->bit_field3() | (1 << Map::kAttachedToSharedFunctionInfo)); + + // Undo state changes made by StartInobjectTracking (except the + // construction_count). This way if the initial map does not survive the GC +@@ -7707,8 +7707,8 @@ void SharedFunctionInfo::DetachInitialMap() { + + // Called from GC, hence reinterpret_cast and unchecked accessors. + void SharedFunctionInfo::AttachInitialMap(Map* map) { +- map->set_bit_field2( +- map->bit_field2() & ~(1 << Map::kAttachedToSharedFunctionInfo)); ++ map->set_bit_field3( ++ map->bit_field3() & ~(1 << Map::kAttachedToSharedFunctionInfo)); + + // Resume inobject slack tracking. + set_initial_map(map); diff --git a/src/objects.h b/src/objects.h -index edbc47a..e75e9f1 100644 +index 73e7f8b..9dcacac 100644 --- a/src/objects.h +++ b/src/objects.h -@@ -3724,6 +3724,11 @@ class Map: public HeapObject { +@@ -4255,6 +4255,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) + +@@ -4502,7 +4507,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; +@@ -4521,6 +4526,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 { +@@ -7553,6 +7559,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 { +@@ -7570,7 +7577,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 5746c20..542e62b 100644 --- a/src/runtime.cc +++ b/src/runtime.cc -@@ -6279,6 +6279,29 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_StringEquals) { +@@ -7095,6 +7095,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 aada06d..cd36da9 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 f30221f..ff8337f 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); - } +@@ -3088,6 +3088,37 @@ void CompareStub::Generate(MacroAssembler* masm) { + // NOTICE! This code is only reached after a smi-fast-case check, so + // it is certain that at least one operand isn't a smi. + { -+ 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; +@@ -5421,8 +5452,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..539014ba12 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 c9277f820ae47f32f127b156ac2e1200458ab876 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 4902e72..cabca74 100644 --- a/src/compiler.cc +++ b/src/compiler.cc -@@ -507,7 +507,7 @@ Handle<SharedFunctionInfo> Compiler::Compile(Handle<String> source, +@@ -499,7 +499,7 @@ Handle<SharedFunctionInfo> Compiler::Compile(Handle<String> source, // Create a script object describing the script to be compiled. Handle<Script> script = FACTORY->NewScript(source); 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..ea87da9431 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 8e095c6171d6be5ac3c90fd2a8707579050d5e47 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 974d702..a16ef65 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 5e90964..6166cde 100644 --- a/src/heap.h +++ b/src/heap.h -@@ -169,6 +169,7 @@ inline Heap* _inline_get_heap_(); +@@ -190,6 +190,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..253f4fd02f 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 bf0c62b53bf018a7f0b3e9ea3dcdcbcc0ee6fd53 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..dc1e1963a2 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 b79ebeab15653e37390ccfca1f6ee252979844ce 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..d4d8d3aace 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 36be1e6b4af4601faa40ea4a222539c6b48f0e03 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..850f70326e 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 e123c9dfe54146f8bfca38841255f63a95a00a19 diff --git a/src/v8/v8.pri b/src/v8/v8.pri index 1d1abc85c0..1c72592c34 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,10 @@ 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 \ + +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 +274,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 |