From 7dc5973bf12919d2d35230844beabe558d4faa00 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Tue, 11 Oct 2011 15:06:25 +1000 Subject: Update V8 Change-Id: I7a9da7dbb2116a441788407d60ed10155cded941 Reviewed-by: Kent Hansen --- src/3rdparty/v8 | 2 +- ...shing-and-comparison-methods-to-v8-String.patch | 136 +- src/v8/0002-Add-a-bit-field-3-to-Map.patch | 118 -- ...back-mode-for-named-property-interceptors.patch | 361 ++++ ...back-mode-for-named-property-interceptors.patch | 364 ---- ...0003-Generalize-external-object-resources.patch | 595 +++++++ ...0004-Generalize-external-object-resources.patch | 894 ---------- src/v8/0004-Introduce-a-QML-compilation-mode.patch | 1871 ++++++++++++++++++++ ...5-Allow-access-to-the-calling-script-data.patch | 48 + src/v8/0005-Introduce-a-QML-compilation-mode.patch | 1856 ------------------- .../0006-Add-custom-object-compare-callback.patch | 548 ++++++ ...6-Allow-access-to-the-calling-script-data.patch | 48 - ...07-Allow-a-script-to-be-flagged-as-native.patch | 46 + src/v8/0007-Fix-warnings.patch | 46 - .../0008-Add-custom-object-compare-callback.patch | 489 ----- ...-Add-new-v8-api-to-check-if-a-value-is-an.patch | 64 + ...unction-method-to-the-Object-class-in-the.patch | 287 --- src/v8/0009-Fix-deprecated-Python-code.patch | 51 + ...allAsConstructor-method-for-Object-in-the.patch | 398 ----- .../0010-Remove-execute-flag-from-v8-debug.h.patch | 15 + src/v8/0011-Fix-warnings.patch | 46 + ...-Add-new-v8-api-to-check-if-a-value-is-an.patch | 64 - ...d-IsCallable-method-for-Object-in-the-API.patch | 116 -- .../0013-Remove-execute-flag-from-v8-debug.h.patch | 15 - src/v8/0014-Fix-deprecated-Python-code.patch | 51 - ...15-Allow-a-script-to-be-flagged-as-native.patch | 46 - ...xternal-resource-to-the-last-hidden-field.patch | 61 - src/v8/README | 2 +- src/v8/v8.pri | 28 +- tests/auto/v8/tst_v8.cpp | 6 + tests/auto/v8/v8main.cpp | 3 + tests/auto/v8/v8test.cpp | 53 + tests/auto/v8/v8test.h | 1 + 33 files changed, 3797 insertions(+), 4932 deletions(-) delete mode 100644 src/v8/0002-Add-a-bit-field-3-to-Map.patch create mode 100644 src/v8/0002-Add-a-fallback-mode-for-named-property-interceptors.patch delete mode 100644 src/v8/0003-Add-a-fallback-mode-for-named-property-interceptors.patch create mode 100644 src/v8/0003-Generalize-external-object-resources.patch delete mode 100644 src/v8/0004-Generalize-external-object-resources.patch create mode 100644 src/v8/0004-Introduce-a-QML-compilation-mode.patch create mode 100644 src/v8/0005-Allow-access-to-the-calling-script-data.patch delete mode 100644 src/v8/0005-Introduce-a-QML-compilation-mode.patch create mode 100644 src/v8/0006-Add-custom-object-compare-callback.patch delete mode 100644 src/v8/0006-Allow-access-to-the-calling-script-data.patch create mode 100644 src/v8/0007-Allow-a-script-to-be-flagged-as-native.patch delete mode 100644 src/v8/0007-Fix-warnings.patch delete mode 100644 src/v8/0008-Add-custom-object-compare-callback.patch create mode 100644 src/v8/0008-QtScript-V8-Add-new-v8-api-to-check-if-a-value-is-an.patch delete mode 100644 src/v8/0009-Add-CallAsFunction-method-to-the-Object-class-in-the.patch create mode 100644 src/v8/0009-Fix-deprecated-Python-code.patch delete mode 100644 src/v8/0010-Implement-CallAsConstructor-method-for-Object-in-the.patch create mode 100644 src/v8/0010-Remove-execute-flag-from-v8-debug.h.patch create mode 100644 src/v8/0011-Fix-warnings.patch delete mode 100644 src/v8/0011-QtScript-V8-Add-new-v8-api-to-check-if-a-value-is-an.patch delete mode 100644 src/v8/0012-Add-IsCallable-method-for-Object-in-the-API.patch delete mode 100644 src/v8/0013-Remove-execute-flag-from-v8-debug.h.patch delete mode 100644 src/v8/0014-Fix-deprecated-Python-code.patch delete mode 100644 src/v8/0015-Allow-a-script-to-be-flagged-as-native.patch delete mode 100644 src/v8/0016-Move-external-resource-to-the-last-hidden-field.patch diff --git a/src/3rdparty/v8 b/src/3rdparty/v8 index 8f15248619..9c0d93bfae 160000 --- a/src/3rdparty/v8 +++ b/src/3rdparty/v8 @@ -1 +1 @@ -Subproject commit 8f15248619bb3bf49473dc3ede8a4e631bd5d199 +Subproject commit 9c0d93bfae724e29ef63456942d9ddca10ca5825 diff --git a/src/v8/0001-Add-hashing-and-comparison-methods-to-v8-String.patch b/src/v8/0001-Add-hashing-and-comparison-methods-to-v8-String.patch index 8a844f5f25..d74624b285 100644 --- a/src/v8/0001-Add-hashing-and-comparison-methods-to-v8-String.patch +++ b/src/v8/0001-Add-hashing-and-comparison-methods-to-v8-String.patch @@ -1,25 +1,25 @@ -From 3dff2e903674d8ab5310d44281b57de36db659c9 Mon Sep 17 00:00:00 2001 +From b0b5bcfbda218aac8e797c19ff6f6de4052d972f Mon Sep 17 00:00:00 2001 From: Aaron Kennedy -Date: Mon, 23 May 2011 15:47:20 +1000 -Subject: [PATCH 01/16] Add hashing and comparison methods to v8::String +Date: Tue, 4 Oct 2011 15:04:21 +1000 +Subject: [PATCH 01/11] Add hashing and comparison methods to v8::String -This allows us to more rapidly search for a v8::String inside -a hash of QStrings. +This allows us to more rapidly search for a v8::String inside a hash +of QStrings. --- - include/v8.h | 45 +++++++++++++++++++++++++++++++ - src/api.cc | 43 +++++++++++++++++++++++++++++ + include/v8.h | 45 +++++++++++++++++++++++++++++ + src/api.cc | 51 +++++++++++++++++++++++++++++++++ src/heap-inl.h | 2 + src/heap.cc | 3 ++ src/objects-inl.h | 1 + - src/objects.cc | 77 ++++++++++++++++++++++++++++++++++++++++++++++++++++- - src/objects.h | 15 +++++++++- - 7 files changed, 183 insertions(+), 3 deletions(-) + src/objects.cc | 82 ++++++++++++++++++++++++++++++++++++++++++++++++++++- + src/objects.h | 10 ++++++- + 7 files changed, 192 insertions(+), 2 deletions(-) diff --git a/include/v8.h b/include/v8.h -index d15d024..be1ee71 100644 +index 73b7fbe..86ea70f 100644 --- a/include/v8.h +++ b/include/v8.h -@@ -994,6 +994,49 @@ class String : public Primitive { +@@ -1021,6 +1021,49 @@ class String : public Primitive { V8EXPORT int Utf8Length() const; /** @@ -69,29 +69,30 @@ index d15d024..be1ee71 100644 * Write the contents of the string to an external buffer. * If no arguments are given, expects the buffer to be large * enough to hold the entire string and NULL terminator. Copies -@@ -1023,6 +1066,8 @@ class String : public Primitive { - HINT_MANY_WRITES_EXPECTED = 1 +@@ -1051,6 +1094,8 @@ class String : public Primitive { + NO_NULL_TERMINATION = 2 }; + V8EXPORT uint16_t GetCharacter(int index); + + // 16-bit character codes. V8EXPORT int Write(uint16_t* buffer, int start = 0, - int length = -1, diff --git a/src/api.cc b/src/api.cc -index a2373cd..381935b 100644 +index 7ae01d1..2d205fd 100644 --- a/src/api.cc +++ b/src/api.cc -@@ -3284,6 +3284,49 @@ int String::Utf8Length() const { - return str->Utf8Length(); +@@ -3652,6 +3652,57 @@ int String::Utf8Length() const { } + +uint32_t String::Hash() const { + i::Handle str = Utils::OpenHandle(this); + if (IsDeadCheck(str->GetIsolate(), "v8::String::Hash()")) return 0; + return str->Hash(); +} + ++ +String::CompleteHashData String::CompleteHash() const { + i::Handle 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(string, length) >> i::String::kHashShift; +} + ++ +uint32_t String::ComputeHash(char *string, int length) { + return i::HashSequentialString(string, length) >> i::String::kHashShift; +} + ++ +uint16_t String::GetCharacter(int index) +{ + i::Handle str = Utils::OpenHandle(this); + return str->Get(index); +} + ++ +bool String::Equals(uint16_t *string, int length) { + i::Handle 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 str = Utils::OpenHandle(this); + if (IsDeadCheck(str->GetIsolate(), "v8::String::Equals()")) return 0; + return str->SlowEqualsExternal(string, length); +} - ++ ++ int String::WriteUtf8(char* buffer, int capacity, + int* nchars_ref, diff --git a/src/heap-inl.h b/src/heap-inl.h -index 99737ed..f4fce7b 100644 +index 4bd893e..a4dfa5a 100644 --- a/src/heap-inl.h +++ b/src/heap-inl.h -@@ -93,6 +93,7 @@ MaybeObject* Heap::AllocateAsciiSymbol(Vector str, +@@ -105,6 +105,7 @@ MaybeObject* Heap::AllocateAsciiSymbol(Vector 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 str, +@@ -138,6 +139,7 @@ MaybeObject* Heap::AllocateTwoByteSymbol(Vector str, String* answer = String::cast(result); answer->set_length(str.length()); answer->set_hash_field(hash_field); @@ -153,18 +161,18 @@ index 99737ed..f4fce7b 100644 ASSERT_EQ(size, answer->Size()); diff --git a/src/heap.cc b/src/heap.cc -index 2b6c11f..930c97b 100644 +index 522861d..0dfd453 100644 --- a/src/heap.cc +++ b/src/heap.cc -@@ -3519,6 +3519,7 @@ MaybeObject* Heap::AllocateInternalSymbol(unibrow::CharacterStream* buffer, +@@ -4061,6 +4061,7 @@ MaybeObject* Heap::AllocateInternalSymbol(unibrow::CharacterStream* buffer, String* answer = String::cast(result); answer->set_length(chars); answer->set_hash_field(hash_field); -+ SeqString::cast(result)->set_symbol_id(0); ++ SeqString::cast(answer)->set_symbol_id(0); ASSERT_EQ(size, answer->Size()); -@@ -3561,6 +3562,7 @@ MaybeObject* Heap::AllocateRawAsciiString(int length, PretenureFlag pretenure) { +@@ -4103,6 +4104,7 @@ MaybeObject* Heap::AllocateRawAsciiString(int length, PretenureFlag pretenure) { HeapObject::cast(result)->set_map(ascii_string_map()); String::cast(result)->set_length(length); String::cast(result)->set_hash_field(String::kEmptyHashField); @@ -172,7 +180,7 @@ index 2b6c11f..930c97b 100644 ASSERT_EQ(size, HeapObject::cast(result)->Size()); return result; } -@@ -3596,6 +3598,7 @@ MaybeObject* Heap::AllocateRawTwoByteString(int length, +@@ -4138,6 +4140,7 @@ MaybeObject* Heap::AllocateRawTwoByteString(int length, HeapObject::cast(result)->set_map(string_map()); String::cast(result)->set_length(length); String::cast(result)->set_hash_field(String::kEmptyHashField); @@ -181,11 +189,11 @@ index 2b6c11f..930c97b 100644 return result; } diff --git a/src/objects-inl.h b/src/objects-inl.h -index 65aec5d..c82080d 100644 +index baf271f..73d0ac9 100644 --- a/src/objects-inl.h +++ b/src/objects-inl.h -@@ -1924,6 +1924,7 @@ INT_ACCESSORS(ExternalArray, length, kLengthOffset) - +@@ -2192,6 +2192,7 @@ SMI_ACCESSORS(FixedArrayBase, length, kLengthOffset) + SMI_ACCESSORS(FreeSpace, size, kSizeOffset) SMI_ACCESSORS(String, length, kLengthOffset) +SMI_ACCESSORS(SeqString, symbol_id, kSymbolIdOffset) @@ -193,13 +201,13 @@ index 65aec5d..c82080d 100644 uint32_t String::hash_field() { diff --git a/src/objects.cc b/src/objects.cc -index df61956..dc4b260 100644 +index 45ae49d..fe5bf97 100644 --- a/src/objects.cc +++ b/src/objects.cc -@@ -5346,6 +5346,66 @@ static inline bool CompareStringContentsPartial(Isolate* isolate, - } +@@ -6242,6 +6242,71 @@ static inline bool CompareStringContentsPartial(Isolate* isolate, } + +bool String::SlowEqualsExternal(uc16 *string, int length) { + int len = this->length(); + if (len != length) return false; @@ -212,13 +220,14 @@ index df61956..dc4b260 100644 + String* lhs = this->TryFlattenGetString(); + + if (lhs->IsFlat()) { ++ String::FlatContent lhs_content = lhs->GetFlatContent(); + if (lhs->IsAsciiRepresentation()) { -+ Vector vec1 = lhs->ToAsciiVector(); ++ Vector vec1 = lhs_content.ToAsciiVector(); + VectorIterator buf1(vec1); + VectorIterator ib(string, length); + return CompareStringContents(&buf1, &ib); + } else { -+ Vector vec1 = lhs->ToUC16Vector(); ++ Vector vec1 = lhs_content.ToUC16Vector(); + Vector 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 vec1 = lhs->ToUC16Vector(); -+ VectorIterator buf1(vec1); -+ VectorIterator buf2(string, length); -+ return CompareStringContents(&buf1, &buf2); ++ String::FlatContent lhs_content = lhs->GetFlatContent(); ++ Vector vec1 = lhs_content.ToUC16Vector(); ++ VectorIterator buf1(vec1); ++ VectorIterator 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 { + int len = length(); +@@ -10103,9 +10168,24 @@ class AsciiSymbolKey : public SequentialSymbolKey { 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 { + class SubStringAsciiSymbolKey : public HashTableKey { diff --git a/src/objects.h b/src/objects.h -index e966b3d..6e26f57 100644 +index 5a1a4a3..eb4eb0e 100644 --- a/src/objects.h +++ b/src/objects.h -@@ -5359,6 +5359,9 @@ class String: public HeapObject { +@@ -5952,6 +5952,9 @@ class String: public HeapObject { bool IsAsciiEqualTo(Vector str); bool IsTwoByteEqualTo(Vector str); @@ -303,42 +316,21 @@ index e966b3d..6e26f57 100644 // Return a UTF8 representation of the string. The string is null // terminated but may optionally contain nulls. Length is returned // in length_output if length_output is not a null pointer The string -@@ -5610,9 +5613,17 @@ class String: public HeapObject { - class SeqString: public String { - public: +@@ -6207,8 +6210,13 @@ class SeqString: public String { + // Casting. + static inline SeqString* cast(Object* obj); + // Get and set the symbol id of the string + inline int symbol_id(); + inline void set_symbol_id(int value); + - // Casting. - static inline SeqString* cast(Object* obj); - -+ // Layout description. -+ static const int kSymbolIdOffset = String::kSize; -+ static const int kSize = kSymbolIdOffset + kPointerSize; -+ - private: - DISALLOW_IMPLICIT_CONSTRUCTORS(SeqString); - }; -@@ -5647,7 +5658,7 @@ class SeqAsciiString: public SeqString { - } - - // Layout description. -- static const int kHeaderSize = String::kSize; -+ static const int kHeaderSize = SeqString::kSize; - static const int kAlignedSize = POINTER_SIZE_ALIGN(kHeaderSize); - - // Maximal memory usage for a single sequential ASCII string. -@@ -5701,7 +5712,7 @@ class SeqTwoByteString: public SeqString { - } - // Layout description. - static const int kHeaderSize = String::kSize; -+ static const int kHeaderSize = SeqString::kSize; - static const int kAlignedSize = POINTER_SIZE_ALIGN(kHeaderSize); ++ static const int kSymbolIdOffset = String::kSize; ++ static const int kHeaderSize = kSymbolIdOffset + kPointerSize; - // Maximal memory usage for a single sequential two-byte string. + // Shortcuts for templates that know their string-type exactly. + bool IsExternalAsciiString() { -- 1.7.4.4 diff --git a/src/v8/0002-Add-a-bit-field-3-to-Map.patch b/src/v8/0002-Add-a-bit-field-3-to-Map.patch deleted file mode 100644 index 59dbad3135..0000000000 --- a/src/v8/0002-Add-a-bit-field-3-to-Map.patch +++ /dev/null @@ -1,118 +0,0 @@ -From 01f7bd262fb1be893fe4bdc6b98a1b43c5a0bb7d Mon Sep 17 00:00:00 2001 -From: Aaron Kennedy -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(result)->set_unused_property_fields(0); - reinterpret_cast(result)->set_bit_field(0); - reinterpret_cast(result)->set_bit_field2(0); -+ reinterpret_cast(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/0002-Add-a-fallback-mode-for-named-property-interceptors.patch b/src/v8/0002-Add-a-fallback-mode-for-named-property-interceptors.patch new file mode 100644 index 0000000000..af42f1555f --- /dev/null +++ b/src/v8/0002-Add-a-fallback-mode-for-named-property-interceptors.patch @@ -0,0 +1,361 @@ +From a80d89daacb698b72f59cad5b83c1f1633a98c9f Mon Sep 17 00:00:00 2001 +From: Aaron Kennedy +Date: Tue, 4 Oct 2011 15:30:20 +1000 +Subject: [PATCH 02/11] Add a "fallback" mode for named property interceptors + +By default interceptors are called before the normal property +resolution on objects. When an interceptor is installed as a +"fallback" interceptor, it is only called if the object doesn't +already have the property. + +In the case of a global object having an fallback interceptor, +the interceptor is not invoked at all for var or function +declarations. +--- + include/v8.h | 7 +++++++ + src/api.cc | 29 +++++++++++++++++++++++++++++ + src/factory.cc | 3 +++ + src/handles.cc | 6 ++++-- + src/handles.h | 3 ++- + src/objects-inl.h | 15 +++++++++++++++ + src/objects.cc | 24 +++++++++++++++++------- + src/objects.h | 16 ++++++++++++---- + src/runtime.cc | 11 ++++++----- + 9 files changed, 95 insertions(+), 19 deletions(-) + +diff --git a/include/v8.h b/include/v8.h +index 86ea70f..d2e6c32 100644 +--- a/include/v8.h ++++ b/include/v8.h +@@ -2305,6 +2305,7 @@ class V8EXPORT FunctionTemplate : public Template { + NamedPropertyQuery query, + NamedPropertyDeleter remover, + NamedPropertyEnumerator enumerator, ++ bool is_fallback, + Handle data); + void SetIndexedInstancePropertyHandler(IndexedPropertyGetter getter, + IndexedPropertySetter setter, +@@ -2388,6 +2389,12 @@ class V8EXPORT ObjectTemplate : public Template { + NamedPropertyDeleter deleter = 0, + NamedPropertyEnumerator enumerator = 0, + Handle data = Handle()); ++ void SetFallbackPropertyHandler(NamedPropertyGetter getter, ++ NamedPropertySetter setter = 0, ++ NamedPropertyQuery query = 0, ++ NamedPropertyDeleter deleter = 0, ++ NamedPropertyEnumerator enumerator = 0, ++ Handle data = Handle()); + + /** + * Sets an indexed property handler on the object template. +diff --git a/src/api.cc b/src/api.cc +index 2d205fd..e4dd694 100644 +--- a/src/api.cc ++++ b/src/api.cc +@@ -1123,6 +1123,7 @@ void FunctionTemplate::SetNamedInstancePropertyHandler( + NamedPropertyQuery query, + NamedPropertyDeleter remover, + NamedPropertyEnumerator enumerator, ++ bool is_fallback, + Handle data) { + i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); + if (IsDeadCheck(isolate, +@@ -1141,6 +1142,7 @@ void FunctionTemplate::SetNamedInstancePropertyHandler( + if (query != 0) SET_FIELD_WRAPPED(obj, set_query, query); + if (remover != 0) SET_FIELD_WRAPPED(obj, set_deleter, remover); + if (enumerator != 0) SET_FIELD_WRAPPED(obj, set_enumerator, enumerator); ++ obj->set_is_fallback(i::Smi::FromInt(is_fallback)); + + if (data.IsEmpty()) data = v8::Undefined(); + obj->set_data(*Utils::OpenHandle(*data)); +@@ -1285,6 +1287,33 @@ void ObjectTemplate::SetNamedPropertyHandler(NamedPropertyGetter getter, + query, + remover, + enumerator, ++ false, ++ data); ++} ++ ++ ++void ObjectTemplate::SetFallbackPropertyHandler(NamedPropertyGetter getter, ++ NamedPropertySetter setter, ++ NamedPropertyQuery query, ++ NamedPropertyDeleter remover, ++ NamedPropertyEnumerator enumerator, ++ Handle data) { ++ i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); ++ if (IsDeadCheck(isolate, "v8::ObjectTemplate::SetNamedPropertyHandler()")) { ++ return; ++ } ++ ENTER_V8(isolate); ++ i::HandleScope scope(isolate); ++ EnsureConstructor(this); ++ i::FunctionTemplateInfo* constructor = ++ i::FunctionTemplateInfo::cast(Utils::OpenHandle(this)->constructor()); ++ i::Handle cons(constructor); ++ Utils::ToLocal(cons)->SetNamedInstancePropertyHandler(getter, ++ setter, ++ query, ++ remover, ++ enumerator, ++ true, + data); + } + +diff --git a/src/factory.cc b/src/factory.cc +index 00fc6bb..2338cda 100644 +--- a/src/factory.cc ++++ b/src/factory.cc +@@ -1180,6 +1180,9 @@ Handle Factory::CreateApiFunction( + // Set interceptor information in the map. + if (!obj->named_property_handler()->IsUndefined()) { + map->set_has_named_interceptor(); ++ InterceptorInfo *nph = InterceptorInfo::cast(obj->named_property_handler()); ++ bool is_fallback = nph->is_fallback()->IsUndefined()?false:nph->is_fallback()->value(); ++ map->set_named_interceptor_is_fallback(is_fallback); + } + if (!obj->indexed_property_handler()->IsUndefined()) { + map->set_has_indexed_interceptor(); +diff --git a/src/handles.cc b/src/handles.cc +index ce4258d..104fc9c 100644 +--- a/src/handles.cc ++++ b/src/handles.cc +@@ -265,9 +265,11 @@ Handle SetProperty(Handle object, + Handle key, + Handle value, + PropertyAttributes attributes, +- StrictModeFlag strict_mode) { ++ StrictModeFlag strict_mode, ++ bool skip_fallback_interceptor) { + CALL_HEAP_FUNCTION(object->GetIsolate(), +- object->SetProperty(*key, *value, attributes, strict_mode), ++ object->SetProperty(*key, *value, attributes, strict_mode, ++ skip_fallback_interceptor), + Object); + } + +diff --git a/src/handles.h b/src/handles.h +index 8dcca3e..babe763 100644 +--- a/src/handles.h ++++ b/src/handles.h +@@ -192,7 +192,8 @@ Handle SetProperty(Handle object, + Handle key, + Handle value, + PropertyAttributes attributes, +- StrictModeFlag strict_mode); ++ StrictModeFlag strict_mode, ++ bool skip_fallback_interceptor = false); + + Handle SetProperty(Handle object, + Handle key, +diff --git a/src/objects-inl.h b/src/objects-inl.h +index 73d0ac9..35fbea5 100644 +--- a/src/objects-inl.h ++++ b/src/objects-inl.h +@@ -2864,6 +2864,20 @@ void Map::set_is_shared(bool value) { + bool Map::is_shared() { + return ((1 << kIsShared) & bit_field3()) != 0; + } ++ ++void Map::set_named_interceptor_is_fallback(bool value) ++{ ++ if (value) { ++ set_bit_field3(bit_field3() | (1 << kNamedInterceptorIsFallback)); ++ } else { ++ set_bit_field3(bit_field3() & ~(1 << kNamedInterceptorIsFallback)); ++ } ++} ++ ++bool Map::named_interceptor_is_fallback() ++{ ++ return ((1 << kNamedInterceptorIsFallback) & bit_field3()) != 0; ++} + + + JSFunction* Map::unchecked_constructor() { +@@ -3350,6 +3364,7 @@ ACCESSORS(InterceptorInfo, query, Object, kQueryOffset) + ACCESSORS(InterceptorInfo, deleter, Object, kDeleterOffset) + ACCESSORS(InterceptorInfo, enumerator, Object, kEnumeratorOffset) + ACCESSORS(InterceptorInfo, data, Object, kDataOffset) ++ACCESSORS(InterceptorInfo, is_fallback, Smi, kFallbackOffset) + + ACCESSORS(CallHandlerInfo, callback, Object, kCallbackOffset) + ACCESSORS(CallHandlerInfo, data, Object, kDataOffset) +diff --git a/src/objects.cc b/src/objects.cc +index fe5bf97..8e1773f 100644 +--- a/src/objects.cc ++++ b/src/objects.cc +@@ -1838,9 +1838,10 @@ MaybeObject* JSObject::SetPropertyWithInterceptor( + MaybeObject* JSReceiver::SetProperty(String* name, + Object* value, + PropertyAttributes attributes, +- StrictModeFlag strict_mode) { ++ StrictModeFlag strict_mode, ++ bool skip_fallback_interceptor) { + LookupResult result; +- LocalLookup(name, &result); ++ LocalLookup(name, &result, skip_fallback_interceptor); + return SetProperty(&result, name, value, attributes, strict_mode); + } + +@@ -3832,7 +3833,8 @@ AccessorDescriptor* Map::FindAccessor(String* name) { + } + + +-void JSReceiver::LocalLookup(String* name, LookupResult* result) { ++void JSReceiver::LocalLookup(String* name, LookupResult* result, ++ bool skip_fallback_interceptor) { + ASSERT(name->IsString()); + + Heap* heap = GetHeap(); +@@ -3864,23 +3866,31 @@ void JSReceiver::LocalLookup(String* name, LookupResult* result) { + } + + // Check for lookup interceptor except when bootstrapping. +- if (js_object->HasNamedInterceptor() && +- !heap->isolate()->bootstrapper()->IsActive()) { ++ bool wouldIntercept = js_object->HasNamedInterceptor() && ++ !heap->isolate()->bootstrapper()->IsActive(); ++ if (wouldIntercept && !map()->named_interceptor_is_fallback()) { + result->InterceptorResult(js_object); + return; + } + + js_object->LocalLookupRealNamedProperty(name, result); ++ ++ if (wouldIntercept && !skip_fallback_interceptor && !result->IsProperty() && ++ map()->named_interceptor_is_fallback()) { ++ result->InterceptorResult(js_object); ++ return; ++ } + } + + +-void JSReceiver::Lookup(String* name, LookupResult* result) { ++void JSReceiver::Lookup(String* name, LookupResult* result, ++ bool skip_fallback_interceptor) { + // Ecma-262 3rd 8.6.2.4 + Heap* heap = GetHeap(); + for (Object* current = this; + current != heap->null_value(); + current = JSObject::cast(current)->GetPrototype()) { +- JSReceiver::cast(current)->LocalLookup(name, result); ++ JSReceiver::cast(current)->LocalLookup(name, result, skip_fallback_interceptor); + if (result->IsProperty()) return; + } + result->NotFound(); +diff --git a/src/objects.h b/src/objects.h +index eb4eb0e..b974756 100644 +--- a/src/objects.h ++++ b/src/objects.h +@@ -1332,7 +1332,8 @@ class JSReceiver: public HeapObject { + MUST_USE_RESULT MaybeObject* SetProperty(String* key, + Object* value, + PropertyAttributes attributes, +- StrictModeFlag strict_mode); ++ StrictModeFlag strict_mode, ++ bool skip_fallback_interceptor = false); + MUST_USE_RESULT MaybeObject* SetProperty(LookupResult* result, + String* key, + Object* value, +@@ -1381,8 +1382,8 @@ class JSReceiver: public HeapObject { + + // Lookup a property. If found, the result is valid and has + // detailed information. +- void LocalLookup(String* name, LookupResult* result); +- void Lookup(String* name, LookupResult* result); ++ void LocalLookup(String* name, LookupResult* result, bool skip_fallback_interceptor = false); ++ void Lookup(String* name, LookupResult* result, bool skip_fallback_interceptor = false); + + protected: + Smi* GenerateIdentityHash(); +@@ -4071,6 +4072,10 @@ class Map: public HeapObject { + inline void set_is_access_check_needed(bool access_check_needed); + inline bool is_access_check_needed(); + ++ // Whether the named interceptor is a fallback interceptor or not ++ inline void set_named_interceptor_is_fallback(bool value); ++ inline bool named_interceptor_is_fallback(); ++ + // [prototype]: implicit prototype object. + DECL_ACCESSORS(prototype, Object) + +@@ -4307,6 +4312,7 @@ class Map: public HeapObject { + + // Bit positions for bit field 3 + static const int kIsShared = 0; ++ static const int kNamedInterceptorIsFallback = 1; + + // Layout of the default cache. It holds alternating name and code objects. + static const int kCodeCacheEntrySize = 2; +@@ -7142,6 +7148,7 @@ class InterceptorInfo: public Struct { + DECL_ACCESSORS(deleter, Object) + DECL_ACCESSORS(enumerator, Object) + DECL_ACCESSORS(data, Object) ++ DECL_ACCESSORS(is_fallback, Smi) + + static inline InterceptorInfo* cast(Object* obj); + +@@ -7161,7 +7168,8 @@ class InterceptorInfo: public Struct { + static const int kDeleterOffset = kQueryOffset + kPointerSize; + static const int kEnumeratorOffset = kDeleterOffset + kPointerSize; + static const int kDataOffset = kEnumeratorOffset + kPointerSize; +- static const int kSize = kDataOffset + kPointerSize; ++ static const int kFallbackOffset = kDataOffset + kPointerSize; ++ static const int kSize = kFallbackOffset + kPointerSize; + + private: + DISALLOW_IMPLICIT_CONSTRUCTORS(InterceptorInfo); +diff --git a/src/runtime.cc b/src/runtime.cc +index 89abf38..5a850e9 100644 +--- a/src/runtime.cc ++++ b/src/runtime.cc +@@ -1236,7 +1236,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareGlobals) { + // Lookup the property in the global object, and don't set the + // value of the variable if the property is already there. + LookupResult lookup; +- global->Lookup(*name, &lookup); ++ global->Lookup(*name, &lookup, true); + if (lookup.IsProperty()) { + // We found an existing property. Unless it was an interceptor + // that claims the property is absent, skip this declaration. +@@ -1263,7 +1263,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareGlobals) { + } + + LookupResult lookup; +- global->LocalLookup(*name, &lookup); ++ global->LocalLookup(*name, &lookup, true); + + // Compute the property attributes. According to ECMA-262, section + // 13, page 71, the property must be read-only and +@@ -1306,7 +1306,8 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareGlobals) { + name, + value, + static_cast(attr), +- strict_mode)); ++ strict_mode, ++ true)); + } + } + +@@ -1442,7 +1443,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeVarGlobal) { + while (object->IsJSObject() && + JSObject::cast(object)->map()->is_hidden_prototype()) { + JSObject* raw_holder = JSObject::cast(object); +- raw_holder->LocalLookup(*name, &lookup); ++ raw_holder->LocalLookup(*name, &lookup, true); + if (lookup.IsProperty() && lookup.type() == INTERCEPTOR) { + HandleScope handle_scope(isolate); + Handle holder(raw_holder); +@@ -1465,7 +1466,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_InitializeVarGlobal) { + // Reload global in case the loop above performed a GC. + global = isolate->context()->global(); + if (assign) { +- return global->SetProperty(*name, args[2], attributes, strict_mode); ++ return global->SetProperty(*name, args[2], attributes, strict_mode, true); + } + return isolate->heap()->undefined_value(); + } +-- +1.7.4.4 + diff --git a/src/v8/0003-Add-a-fallback-mode-for-named-property-interceptors.patch b/src/v8/0003-Add-a-fallback-mode-for-named-property-interceptors.patch deleted file mode 100644 index 78184f6f9d..0000000000 --- a/src/v8/0003-Add-a-fallback-mode-for-named-property-interceptors.patch +++ /dev/null @@ -1,364 +0,0 @@ -From 530ded6ea634bccb96652cd3e0cf67725449ed63 Mon Sep 17 00:00:00 2001 -From: Aaron Kennedy -Date: Mon, 23 May 2011 16:21:02 +1000 -Subject: [PATCH 03/16] Add a "fallback" mode for named property interceptors - -By default interceptors are called before the normal property -resolution on objects. When an interceptor is installed as a -"fallback" interceptor, it is only called if the object doesn't -already have the property. - -In the case of a global object having an fallback interceptor, -the interceptor is not invoked at all for var or function -declarations. ---- - include/v8.h | 8 ++++++++ - src/api.cc | 29 +++++++++++++++++++++++++++++ - src/factory.cc | 4 ++++ - src/handles.cc | 6 ++++-- - src/handles.h | 3 ++- - src/objects-inl.h | 16 ++++++++++++++++ - src/objects.cc | 22 ++++++++++++++++------ - src/objects.h | 18 ++++++++++++++---- - src/runtime.cc | 11 ++++++----- - 9 files changed, 99 insertions(+), 18 deletions(-) - -diff --git a/include/v8.h b/include/v8.h -index be1ee71..bb31ea0 100644 ---- a/include/v8.h -+++ b/include/v8.h -@@ -2170,6 +2170,7 @@ class V8EXPORT FunctionTemplate : public Template { - NamedPropertyQuery query, - NamedPropertyDeleter remover, - NamedPropertyEnumerator enumerator, -+ bool is_fallback, - Handle data); - void SetIndexedInstancePropertyHandler(IndexedPropertyGetter getter, - IndexedPropertySetter setter, -@@ -2254,6 +2255,13 @@ class V8EXPORT ObjectTemplate : public Template { - NamedPropertyEnumerator enumerator = 0, - Handle data = Handle()); - -+ void SetFallbackPropertyHandler(NamedPropertyGetter getter, -+ NamedPropertySetter setter = 0, -+ NamedPropertyQuery query = 0, -+ NamedPropertyDeleter deleter = 0, -+ NamedPropertyEnumerator enumerator = 0, -+ Handle data = Handle()); -+ - /** - * Sets an indexed property handler on the object template. - * -diff --git a/src/api.cc b/src/api.cc -index 381935b..8b0b32a 100644 ---- a/src/api.cc -+++ b/src/api.cc -@@ -981,6 +981,7 @@ void FunctionTemplate::SetNamedInstancePropertyHandler( - NamedPropertyQuery query, - NamedPropertyDeleter remover, - NamedPropertyEnumerator enumerator, -+ bool is_fallback, - Handle data) { - i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); - if (IsDeadCheck(isolate, -@@ -999,6 +1000,7 @@ void FunctionTemplate::SetNamedInstancePropertyHandler( - if (query != 0) SET_FIELD_WRAPPED(obj, set_query, query); - if (remover != 0) SET_FIELD_WRAPPED(obj, set_deleter, remover); - if (enumerator != 0) SET_FIELD_WRAPPED(obj, set_enumerator, enumerator); -+ obj->set_is_fallback(i::Smi::FromInt(is_fallback)); - - if (data.IsEmpty()) data = v8::Undefined(); - obj->set_data(*Utils::OpenHandle(*data)); -@@ -1143,6 +1145,33 @@ void ObjectTemplate::SetNamedPropertyHandler(NamedPropertyGetter getter, - query, - remover, - enumerator, -+ false, -+ data); -+} -+ -+ -+void ObjectTemplate::SetFallbackPropertyHandler(NamedPropertyGetter getter, -+ NamedPropertySetter setter, -+ NamedPropertyQuery query, -+ NamedPropertyDeleter remover, -+ NamedPropertyEnumerator enumerator, -+ Handle data) { -+ i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); -+ if (IsDeadCheck(isolate, "v8::ObjectTemplate::SetFallbackPropertyHandler()")) { -+ return; -+ } -+ ENTER_V8(isolate); -+ i::HandleScope scope(isolate); -+ EnsureConstructor(this); -+ i::FunctionTemplateInfo* constructor = -+ i::FunctionTemplateInfo::cast(Utils::OpenHandle(this)->constructor()); -+ i::Handle cons(constructor); -+ Utils::ToLocal(cons)->SetNamedInstancePropertyHandler(getter, -+ setter, -+ query, -+ remover, -+ enumerator, -+ true, - data); - } - -diff --git a/src/factory.cc b/src/factory.cc -index 7dee66f..dcdc645 100644 ---- a/src/factory.cc -+++ b/src/factory.cc -@@ -1058,6 +1058,10 @@ Handle Factory::CreateApiFunction( - // Set interceptor information in the map. - if (!obj->named_property_handler()->IsUndefined()) { - map->set_has_named_interceptor(); -+ -+ InterceptorInfo *nph = InterceptorInfo::cast(obj->named_property_handler()); -+ bool is_fallback = nph->is_fallback()->IsUndefined()?false:nph->is_fallback()->value(); -+ map->set_named_interceptor_is_fallback(is_fallback); - } - if (!obj->indexed_property_handler()->IsUndefined()) { - map->set_has_indexed_interceptor(); -diff --git a/src/handles.cc b/src/handles.cc -index 326de86..dd3a86c 100644 ---- a/src/handles.cc -+++ b/src/handles.cc -@@ -262,9 +262,11 @@ Handle SetProperty(Handle object, - Handle key, - Handle value, - PropertyAttributes attributes, -- StrictModeFlag strict_mode) { -+ StrictModeFlag strict_mode, -+ bool skip_fallback_interceptor) { - CALL_HEAP_FUNCTION(object->GetIsolate(), -- object->SetProperty(*key, *value, attributes, strict_mode), -+ object->SetProperty(*key, *value, attributes, strict_mode, -+ skip_fallback_interceptor), - Object); - } - -diff --git a/src/handles.h b/src/handles.h -index 3839f37..4b42506 100644 ---- a/src/handles.h -+++ b/src/handles.h -@@ -188,7 +188,8 @@ Handle SetProperty(Handle object, - Handle key, - Handle value, - PropertyAttributes attributes, -- StrictModeFlag strict_mode); -+ StrictModeFlag strict_mode, -+ bool skip_fallback_interceptor = false); - - Handle SetProperty(Handle object, - Handle key, -diff --git a/src/objects-inl.h b/src/objects-inl.h -index cce3edd..6aaca2f 100644 ---- a/src/objects-inl.h -+++ b/src/objects-inl.h -@@ -2521,6 +2521,21 @@ bool Map::is_shared() { - } - - -+void Map::set_named_interceptor_is_fallback(bool value) -+{ -+ if (value) { -+ set_bit_field3(bit_field3() | (1 << kNamedInterceptorIsFallback)); -+ } else { -+ set_bit_field3(bit_field3() & ~(1 << kNamedInterceptorIsFallback)); -+ } -+} -+ -+bool Map::named_interceptor_is_fallback() -+{ -+ return ((1 << kNamedInterceptorIsFallback) & bit_field3()) != 0; -+} -+ -+ - JSFunction* Map::unchecked_constructor() { - return reinterpret_cast(READ_FIELD(this, kConstructorOffset)); - } -@@ -2970,6 +2985,7 @@ ACCESSORS(InterceptorInfo, query, Object, kQueryOffset) - ACCESSORS(InterceptorInfo, deleter, Object, kDeleterOffset) - ACCESSORS(InterceptorInfo, enumerator, Object, kEnumeratorOffset) - ACCESSORS(InterceptorInfo, data, Object, kDataOffset) -+ACCESSORS(InterceptorInfo, is_fallback, Smi, kFallbackOffset) - - ACCESSORS(CallHandlerInfo, callback, Object, kCallbackOffset) - ACCESSORS(CallHandlerInfo, data, Object, kDataOffset) -diff --git a/src/objects.cc b/src/objects.cc -index 79d7240..15e2cdb 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; -- 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) { - } - - --void JSObject::LocalLookup(String* name, LookupResult* result) { -+void JSObject::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) { - } - - // Check for lookup interceptor except when bootstrapping. -- if (HasNamedInterceptor() && !heap->isolate()->bootstrapper()->IsActive()) { -+ bool wouldIntercept = HasNamedInterceptor() && !heap->isolate()->bootstrapper()->IsActive(); -+ if (wouldIntercept && !map()->named_interceptor_is_fallback()) { - result->InterceptorResult(this); - return; - } - - LocalLookupRealNamedProperty(name, result); -+ -+ if (wouldIntercept && !skip_fallback_interceptor && !result->IsProperty() && -+ map()->named_interceptor_is_fallback()) { -+ result->InterceptorResult(this); -+ return; -+ } - } - - --void JSObject::Lookup(String* name, LookupResult* result) { -+void JSObject::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); - if (result->IsProperty()) return; - } - result->NotFound(); -diff --git a/src/objects.h b/src/objects.h -index 07e1089..a209cd0 100644 ---- a/src/objects.h -+++ b/src/objects.h -@@ -1405,7 +1405,8 @@ class JSObject: public HeapObject { - MUST_USE_RESULT MaybeObject* SetProperty(String* key, - Object* value, - PropertyAttributes attributes, -- StrictModeFlag strict_mode); -+ StrictModeFlag strict_mode, -+ bool skip_fallback_interceptor = false); - MUST_USE_RESULT MaybeObject* SetProperty(LookupResult* result, - String* key, - Object* value, -@@ -1637,8 +1638,8 @@ class JSObject: public HeapObject { - - // Lookup a property. If found, the result is valid and has - // detailed information. -- void LocalLookup(String* name, LookupResult* result); -- void Lookup(String* name, LookupResult* result); -+ void LocalLookup(String* name, LookupResult* result, bool skip_fallback_interceptor = false); -+ void Lookup(String* name, LookupResult* result, bool skip_fallback_interceptor = false); - - // The following lookup functions skip interceptors. - void LocalLookupRealNamedProperty(String* name, LookupResult* result); -@@ -3714,6 +3715,12 @@ 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; - - // Bit positions for bit field 3 -+ static const int kNamedInterceptorIsFallback = 0; - - // 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 { - DECL_ACCESSORS(deleter, Object) - DECL_ACCESSORS(enumerator, Object) - DECL_ACCESSORS(data, Object) -+ DECL_ACCESSORS(is_fallback, Smi) - - static inline InterceptorInfo* cast(Object* obj); - -@@ -6295,7 +6304,8 @@ class InterceptorInfo: public Struct { - static const int kDeleterOffset = kQueryOffset + kPointerSize; - static const int kEnumeratorOffset = kDeleterOffset + kPointerSize; - static const int kDataOffset = kEnumeratorOffset + kPointerSize; -- static const int kSize = kDataOffset + kPointerSize; -+ static const int kFallbackOffset = kDataOffset + kPointerSize; -+ static const int kSize = kFallbackOffset + kPointerSize; - - private: - DISALLOW_IMPLICIT_CONSTRUCTORS(InterceptorInfo); -diff --git a/src/runtime.cc b/src/runtime.cc -index 7335da8..660352c 100644 ---- a/src/runtime.cc -+++ b/src/runtime.cc -@@ -1097,7 +1097,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareGlobals) { - // Lookup the property in the global object, and don't set the - // value of the variable if the property is already there. - LookupResult lookup; -- global->Lookup(*name, &lookup); -+ global->Lookup(*name, &lookup, true); - if (lookup.IsProperty()) { - // Determine if the property is local by comparing the holder - // against the global object. The information will be used to -@@ -1152,7 +1152,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareGlobals) { - } - - LookupResult lookup; -- global->LocalLookup(*name, &lookup); -+ global->LocalLookup(*name, &lookup, true); - - PropertyAttributes attributes = is_const_property - ? static_cast(base | READ_ONLY) -@@ -1196,7 +1196,8 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareGlobals) { - name, - value, - attributes, -- 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) { - - global = isolate->context()->global(); - if (assign) { -- return global->SetProperty(*name, args[2], attributes, strict_mode); -+ return global->SetProperty(*name, args[2], attributes, strict_mode, true); - } - return isolate->heap()->undefined_value(); - } --- -1.7.4.4 - diff --git a/src/v8/0003-Generalize-external-object-resources.patch b/src/v8/0003-Generalize-external-object-resources.patch new file mode 100644 index 0000000000..658a09126a --- /dev/null +++ b/src/v8/0003-Generalize-external-object-resources.patch @@ -0,0 +1,595 @@ +From be5bc4e5ea15dd74c2753c30c25a4660598274c3 Mon Sep 17 00:00:00 2001 +From: Aaron Kennedy +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 key); + V8EXPORT bool HasRealNamedProperty(Handle 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 New(Handle constructor); +diff --git a/src/api.cc b/src/api.cc +index e4dd694..85f0d4b 100644 +--- a/src/api.cc ++++ b/src/api.cc +@@ -1436,6 +1436,34 @@ void ObjectTemplate::SetInternalFieldCount(int value) { + } + + ++bool ObjectTemplate::HasExternalResource() ++{ ++ if (IsDeadCheck(Utils::OpenHandle(this)->GetIsolate(), ++ "v8::ObjectTemplate::HasExternalResource()")) { ++ return 0; ++ } ++ return !Utils::OpenHandle(this)->has_external_resource()->IsUndefined(); ++} ++ ++ ++void ObjectTemplate::SetHasExternalResource(bool value) ++{ ++ i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); ++ if (IsDeadCheck(isolate, "v8::ObjectTemplate::SetHasExternalResource()")) { ++ return; ++ } ++ ENTER_V8(isolate); ++ if (value) { ++ EnsureConstructor(this); ++ } ++ if (value) { ++ Utils::OpenHandle(this)->set_has_external_resource(i::Smi::FromInt(1)); ++ } else { ++ Utils::OpenHandle(this)->set_has_external_resource(Utils::OpenHandle(this)->GetHeap()->undefined_value()); ++ } ++} ++ ++ + // --- S c r i p t D a t a --- + + +@@ -4031,6 +4059,34 @@ void v8::Object::SetPointerInInternalField(int index, void* value) { + } + + ++void v8::Object::SetExternalResource(v8::Object::ExternalResource *resource) { ++ i::Isolate* isolate = Utils::OpenHandle(this)->GetIsolate(); ++ ENTER_V8(isolate); ++ i::Handle obj = Utils::OpenHandle(this); ++ if (CanBeEncodedAsSmi(resource)) { ++ obj->SetExternalResourceObject(EncodeAsSmi(resource)); ++ } else { ++ obj->SetExternalResourceObject(*isolate->factory()->NewForeign(static_cast((void *)resource))); ++ } ++ if (!obj->IsSymbol()) { ++ isolate->heap()->external_string_table()->AddObject(*obj); ++ } ++} ++ ++ ++v8::Object::ExternalResource *v8::Object::GetExternalResource() { ++ i::Handle obj = Utils::OpenHandle(this); ++ i::Object* value = obj->GetExternalResourceObject(); ++ if (value->IsSmi()) { ++ return reinterpret_cast(i::Internals::GetExternalPointerFromSmi(value)); ++ } else if (value->IsForeign()) { ++ return reinterpret_cast(i::Foreign::cast(value)->address()); ++ } else { ++ return NULL; ++ } ++} ++ ++ + // --- E n v i r o n m e n t --- + + +diff --git a/src/factory.cc b/src/factory.cc +index 2338cda..e3cccae 100644 +--- a/src/factory.cc ++++ b/src/factory.cc +@@ -1119,15 +1119,21 @@ Handle Factory::CreateApiFunction( + Handle construct_stub = isolate()->builtins()->JSConstructStubApi(); + + int internal_field_count = 0; ++ bool has_external_resource = false; ++ + if (!obj->instance_template()->IsUndefined()) { + Handle instance_template = + Handle( + ObjectTemplateInfo::cast(obj->instance_template())); + internal_field_count = + Smi::cast(instance_template->internal_field_count())->value(); ++ has_external_resource = ++ !instance_template->has_external_resource()->IsUndefined(); + } + + int instance_size = kPointerSize * internal_field_count; ++ if (has_external_resource) instance_size += kPointerSize; ++ + InstanceType type = INVALID_TYPE; + switch (instance_type) { + case JavaScriptObject: +@@ -1162,6 +1168,11 @@ Handle Factory::CreateApiFunction( + + Handle map = Handle(result->initial_map()); + ++ // Mark as having external data object if needed ++ if (has_external_resource) { ++ map->set_has_external_resource(true); ++ } ++ + // Mark as undetectable if needed. + if (obj->undetectable()) { + map->set_is_undetectable(); +diff --git a/src/heap-inl.h b/src/heap-inl.h +index a4dfa5a..b121d01 100644 +--- a/src/heap-inl.h ++++ b/src/heap-inl.h +@@ -222,21 +222,36 @@ MaybeObject* Heap::NumberFromUint32(uint32_t value) { + } + + +-void Heap::FinalizeExternalString(String* string) { +- ASSERT(string->IsExternalString()); +- v8::String::ExternalStringResourceBase** resource_addr = +- reinterpret_cast( +- reinterpret_cast(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( ++ reinterpret_cast(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(Internals::GetExternalPointerFromSmi(value)); ++ } else if (value->IsForeign()) { ++ resource = reinterpret_cast(Foreign::cast(value)->address()); ++ } ++ if (resource) { ++ resource->Dispose(); ++ } + } +- +- // Clear the resource pointer in the string. +- *resource_addr = NULL; + } + + +@@ -556,6 +571,16 @@ void ExternalStringTable::AddString(String* string) { + } + + ++void ExternalStringTable::AddObject(HeapObject* object) { ++ ASSERT(object->map()->has_external_resource()); ++ if (heap_->InNewSpace(object)) { ++ new_space_strings_.Add(object); ++ } else { ++ old_space_strings_.Add(object); ++ } ++} ++ ++ + void ExternalStringTable::Iterate(ObjectVisitor* v) { + if (!new_space_strings_.is_empty()) { + Object** start = &new_space_strings_[0]; +@@ -584,14 +609,14 @@ void ExternalStringTable::Verify() { + } + + +-void ExternalStringTable::AddOldString(String* string) { +- ASSERT(string->IsExternalString()); +- ASSERT(!heap_->InNewSpace(string)); +- old_space_strings_.Add(string); ++void ExternalStringTable::AddOldObject(HeapObject* object) { ++ ASSERT(object->IsExternalString() || object->map()->has_external_resource()); ++ ASSERT(!heap_->InNewSpace(object)); ++ old_space_strings_.Add(object); + } + + +-void ExternalStringTable::ShrinkNewStrings(int position) { ++void ExternalStringTable::ShrinkNewObjects(int position) { + new_space_strings_.Rewind(position); + Verify(); + } +diff --git a/src/heap.cc b/src/heap.cc +index 0dfd453..c730455 100644 +--- a/src/heap.cc ++++ b/src/heap.cc +@@ -1095,18 +1095,18 @@ void Heap::Scavenge() { + } + + +-String* Heap::UpdateNewSpaceReferenceInExternalStringTableEntry(Heap* heap, +- Object** p) { ++HeapObject* Heap::UpdateNewSpaceReferenceInExternalStringTableEntry(Heap* heap, ++ Object** p) { + MapWord first_word = HeapObject::cast(*p)->map_word(); + + if (!first_word.IsForwardingAddress()) { + // Unreachable external string can be finalized. +- heap->FinalizeExternalString(String::cast(*p)); ++ heap->FinalizeExternalString(HeapObject::cast(*p)); + return NULL; + } + + // String is still reachable. +- return String::cast(first_word.ToForwardingAddress()); ++ return HeapObject::cast(first_word.ToForwardingAddress()); + } + + +@@ -1122,11 +1122,11 @@ void Heap::UpdateNewSpaceReferencesInExternalStringTable( + + for (Object** p = start; p < end; ++p) { + ASSERT(InFromSpace(*p)); +- String* target = updater_func(this, p); ++ HeapObject* target = updater_func(this, p); + + if (target == NULL) continue; + +- ASSERT(target->IsExternalString()); ++ ASSERT(target->IsExternalString() || target->map()->has_external_resource()); + + if (InNewSpace(target)) { + // String is still in new space. Update the table entry. +@@ -1134,12 +1134,12 @@ void Heap::UpdateNewSpaceReferencesInExternalStringTable( + ++last; + } else { + // String got promoted. Move it to the old string list. +- external_string_table_.AddOldString(target); ++ external_string_table_.AddOldObject(target); + } + } + + ASSERT(last <= end); +- external_string_table_.ShrinkNewStrings(static_cast(last - start)); ++ external_string_table_.ShrinkNewObjects(static_cast(last - start)); + } + + +@@ -6426,6 +6426,19 @@ void ExternalStringTable::CleanUp() { + + + void ExternalStringTable::TearDown() { ++ for (int i = 0; i < new_space_strings_.length(); ++i) { ++ if (new_space_strings_[i] == heap_->raw_unchecked_null_value()) continue; ++ HeapObject *object = HeapObject::cast(new_space_strings_[i]); ++ if (!object->IsExternalString()) ++ heap_->FinalizeExternalString(object); ++ } ++ for (int i = 0; i < old_space_strings_.length(); ++i) { ++ if (old_space_strings_[i] == heap_->raw_unchecked_null_value()) continue; ++ HeapObject *object = HeapObject::cast(old_space_strings_[i]); ++ if (!object->IsExternalString()) ++ heap_->FinalizeExternalString(object); ++ } ++ + new_space_strings_.Free(); + old_space_strings_.Free(); + } +diff --git a/src/heap.h b/src/heap.h +index 4a1e01d..bab4c63 100644 +--- a/src/heap.h ++++ b/src/heap.h +@@ -243,8 +243,8 @@ class Isolate; + class WeakObjectRetainer; + + +-typedef String* (*ExternalStringTableUpdaterCallback)(Heap* heap, +- Object** pointer); ++typedef HeapObject* (*ExternalStringTableUpdaterCallback)(Heap* heap, ++ Object** pointer); + + class StoreBufferRebuilder { + public: +@@ -329,10 +329,14 @@ typedef void (*ScavengingCallback)(Map* map, + // External strings table is a place where all external strings are + // registered. We need to keep track of such strings to properly + // finalize them. ++// The ExternalStringTable can contain both strings and objects with ++// external resources. It was not renamed to make the patch simpler. + class ExternalStringTable { + public: + // Registers an external string. + inline void AddString(String* string); ++ // Registers an external object. ++ inline void AddObject(HeapObject* string); + + inline void Iterate(ObjectVisitor* v); + +@@ -350,10 +354,10 @@ class ExternalStringTable { + + inline void Verify(); + +- inline void AddOldString(String* string); ++ inline void AddOldObject(HeapObject* string); + + // Notifies the table that only a prefix of the new list is valid. +- inline void ShrinkNewStrings(int position); ++ inline void ShrinkNewObjects(int position); + + // To speed up scavenge collections new space string are kept + // separate from old space strings. +@@ -849,7 +853,7 @@ class Heap { + + // Finalizes an external string by deleting the associated external + // data and clearing the resource pointer. +- inline void FinalizeExternalString(String* string); ++ inline void FinalizeExternalString(HeapObject* string); + + // Allocates an uninitialized object. The memory is non-executable if the + // hardware and OS allow. +@@ -1662,7 +1666,7 @@ class Heap { + // Performs a minor collection in new generation. + void Scavenge(); + +- static String* UpdateNewSpaceReferenceInExternalStringTableEntry( ++ static HeapObject* UpdateNewSpaceReferenceInExternalStringTableEntry( + Heap* heap, + Object** pointer); + +diff --git a/src/mark-compact.cc b/src/mark-compact.cc +index e90a23d..b9ae787 100644 +--- a/src/mark-compact.cc ++++ b/src/mark-compact.cc +@@ -1521,8 +1521,9 @@ class SymbolTableCleaner : public ObjectVisitor { + + // Since no objects have yet been moved we can safely access the map of + // the object. +- if (o->IsExternalString()) { +- heap_->FinalizeExternalString(String::cast(*p)); ++ if (o->IsExternalString() || ++ (o->IsHeapObject() && HeapObject::cast(o)->map()->has_external_resource())) { ++ heap_->FinalizeExternalString(HeapObject::cast(*p)); + } + // Set the entry to null_value (as deleted). + *p = heap_->null_value(); +@@ -2515,15 +2516,15 @@ static void UpdatePointer(HeapObject** p, HeapObject* object) { + } + + +-static String* UpdateReferenceInExternalStringTableEntry(Heap* heap, +- Object** p) { ++static HeapObject* UpdateReferenceInExternalStringTableEntry(Heap* heap, ++ Object** p) { + MapWord map_word = HeapObject::cast(*p)->map_word(); + + if (map_word.IsForwardingAddress()) { +- return String::cast(map_word.ToForwardingAddress()); ++ return HeapObject::cast(map_word.ToForwardingAddress()); + } + +- return String::cast(*p); ++ return HeapObject::cast(*p); + } + + +diff --git a/src/objects-inl.h b/src/objects-inl.h +index 35fbea5..36af868 100644 +--- a/src/objects-inl.h ++++ b/src/objects-inl.h +@@ -1488,7 +1488,7 @@ int JSObject::GetInternalFieldCount() { + // Make sure to adjust for the number of in-object properties. These + // properties do contribute to the size, but are not internal fields. + return ((Size() - GetHeaderSize()) >> kPointerSizeLog2) - +- map()->inobject_properties(); ++ map()->inobject_properties() - (map()->has_external_resource()?1:0); + } + + +@@ -1518,6 +1518,23 @@ void JSObject::SetInternalField(int index, Object* value) { + } + + ++void JSObject::SetExternalResourceObject(Object *value) { ++ ASSERT(map()->has_external_resource()); ++ int offset = GetHeaderSize() + kPointerSize * GetInternalFieldCount(); ++ WRITE_FIELD(this, offset, value); ++ WRITE_BARRIER(GetHeap(), this, offset, value); ++} ++ ++ ++Object *JSObject::GetExternalResourceObject() { ++ if (map()->has_external_resource()) { ++ return READ_FIELD(this, GetHeaderSize() + kPointerSize * GetInternalFieldCount()); ++ } else { ++ return GetHeap()->undefined_value(); ++ } ++} ++ ++ + // Access fast-case object properties at index. The use of these routines + // is needed to correctly distinguish between properties stored in-object and + // properties stored in the properties array. +@@ -2865,6 +2882,20 @@ bool Map::is_shared() { + return ((1 << kIsShared) & bit_field3()) != 0; + } + ++void Map::set_has_external_resource(bool value) { ++ if (value) { ++ set_bit_field(bit_field() | (1 << kHasExternalResource)); ++ } else { ++ set_bit_field(bit_field() & ~(1 << kHasExternalResource)); ++ } ++} ++ ++bool Map::has_external_resource() ++{ ++ return ((1 << kHasExternalResource) & bit_field()) != 0; ++} ++ ++ + void Map::set_named_interceptor_is_fallback(bool value) + { + if (value) { +@@ -3396,6 +3427,8 @@ ACCESSORS(FunctionTemplateInfo, flag, Smi, kFlagOffset) + ACCESSORS(ObjectTemplateInfo, constructor, Object, kConstructorOffset) + ACCESSORS(ObjectTemplateInfo, internal_field_count, Object, + kInternalFieldCountOffset) ++ACCESSORS(ObjectTemplateInfo, has_external_resource, Object, ++ kHasExternalResourceOffset) + + ACCESSORS(SignatureInfo, receiver, Object, kReceiverOffset) + ACCESSORS(SignatureInfo, args, Object, kArgsOffset) +diff --git a/src/objects.h b/src/objects.h +index b974756..dea5bbd 100644 +--- a/src/objects.h ++++ b/src/objects.h +@@ -1732,6 +1732,9 @@ class JSObject: public JSReceiver { + inline Object* GetInternalField(int index); + inline void SetInternalField(int index, Object* value); + ++ inline void SetExternalResourceObject(Object *); ++ inline Object *GetExternalResourceObject(); ++ + // The following lookup functions skip interceptors. + void LocalLookupRealNamedProperty(String* name, LookupResult* result); + void LookupRealNamedProperty(String* name, LookupResult* result); +@@ -4003,11 +4006,11 @@ class Map: public HeapObject { + + // Tells whether the instance has a call-as-function handler. + inline void set_has_instance_call_handler() { +- set_bit_field(bit_field() | (1 << kHasInstanceCallHandler)); ++ set_bit_field3(bit_field3() | (1 << kHasInstanceCallHandler)); + } + + inline bool has_instance_call_handler() { +- return ((1 << kHasInstanceCallHandler) & bit_field()) != 0; ++ return ((1 << kHasInstanceCallHandler) & bit_field3()) != 0; + } + + inline void set_is_extensible(bool value); +@@ -4076,6 +4079,11 @@ class Map: public HeapObject { + inline void set_named_interceptor_is_fallback(bool value); + inline bool named_interceptor_is_fallback(); + ++ // Tells whether the instance has the space for an external resource ++ // object ++ inline void set_has_external_resource(bool value); ++ inline bool has_external_resource(); ++ + // [prototype]: implicit prototype object. + DECL_ACCESSORS(prototype, Object) + +@@ -4288,7 +4296,7 @@ class Map: public HeapObject { + static const int kHasNamedInterceptor = 3; + static const int kHasIndexedInterceptor = 4; + static const int kIsUndetectable = 5; +- static const int kHasInstanceCallHandler = 6; ++ static const int kHasExternalResource = 6; + static const int kIsAccessCheckNeeded = 7; + + // Bit positions for bit field 2 +@@ -4313,6 +4321,7 @@ class Map: public HeapObject { + // Bit positions for bit field 3 + static const int kIsShared = 0; + static const int kNamedInterceptorIsFallback = 1; ++ static const int kHasInstanceCallHandler = 2; + + // Layout of the default cache. It holds alternating name and code objects. + static const int kCodeCacheEntrySize = 2; +@@ -7292,6 +7301,7 @@ class ObjectTemplateInfo: public TemplateInfo { + public: + DECL_ACCESSORS(constructor, Object) + DECL_ACCESSORS(internal_field_count, Object) ++ DECL_ACCESSORS(has_external_resource, Object) + + static inline ObjectTemplateInfo* cast(Object* obj); + +@@ -7308,7 +7318,8 @@ class ObjectTemplateInfo: public TemplateInfo { + static const int kConstructorOffset = TemplateInfo::kHeaderSize; + static const int kInternalFieldCountOffset = + kConstructorOffset + kPointerSize; +- static const int kSize = kInternalFieldCountOffset + kPointerSize; ++ static const int kHasExternalResourceOffset = kInternalFieldCountOffset + kPointerSize; ++ static const int kSize = kHasExternalResourceOffset + kPointerSize; + }; + + +-- +1.7.4.4 + diff --git a/src/v8/0004-Generalize-external-object-resources.patch b/src/v8/0004-Generalize-external-object-resources.patch deleted file mode 100644 index ece0f197d8..0000000000 --- a/src/v8/0004-Generalize-external-object-resources.patch +++ /dev/null @@ -1,894 +0,0 @@ -From f9368b52060c31e9532ef26f6cca1a2cb0283f51 Mon Sep 17 00:00:00 2001 -From: Aaron Kennedy -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 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 New(Handle 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 obj = Utils::OpenHandle(this); -+ if (CanBeEncodedAsSmi(resource)) { -+ obj->SetExternalResourceObject(EncodeAsSmi(resource)); -+ } else { -+ obj->SetExternalResourceObject(*isolate->factory()->NewProxy(static_cast((void *)resource))); -+ } -+ if (!obj->IsSymbol()) { -+ isolate->heap()->external_resource_table()->AddObject(*obj); -+ } -+} -+ -+ -+v8::Object::ExternalResource *v8::Object::GetExternalResource() { -+ i::Handle obj = Utils::OpenHandle(this); -+ i::Object* value = obj->GetExternalResourceObject(); -+ if (value->IsSmi()) { -+ return reinterpret_cast(i::Internals::GetExternalPointerFromSmi(value)); -+ } else if (value->IsProxy()) { -+ return reinterpret_cast(i::Proxy::cast(value)->proxy()); -+ } else { -+ return NULL; -+ } -+} -+ -+ - // --- E n v i r o n m e n t --- - - -@@ -4144,7 +4200,7 @@ Local v8::String::NewExternal( - LOG_API(isolate, "String::NewExternal"); - ENTER_V8(isolate); - i::Handle 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 v8::String::NewExternal( - LOG_API(isolate, "String::NewExternal"); - ENTER_V8(isolate); - i::Handle 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 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 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 Factory::CreateApiFunction( - Handle construct_stub = isolate()->builtins()->JSConstructStubApi(); - - int internal_field_count = 0; -+ bool has_external_resource = false; -+ - if (!obj->instance_template()->IsUndefined()) { - Handle instance_template = - Handle( - 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 Factory::CreateApiFunction( - - Handle map = Handle(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( -- reinterpret_cast(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( -+ reinterpret_cast(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(Internals::GetExternalPointerFromSmi(value)); -+ } else if (value->IsProxy()) { -+ resource = reinterpret_cast(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(last - start)); -+ external_resource_table_.ShrinkNewObjects(static_cast(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 new_space_strings_; -- List old_space_strings_; -+ List new_space_objects_; -+ List 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 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 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/0004-Introduce-a-QML-compilation-mode.patch b/src/v8/0004-Introduce-a-QML-compilation-mode.patch new file mode 100644 index 0000000000..4b79d94e68 --- /dev/null +++ b/src/v8/0004-Introduce-a-QML-compilation-mode.patch @@ -0,0 +1,1871 @@ +From 27ef7b7b37255a9965fe31fb7597720f57ed5154 Mon Sep 17 00:00:00 2001 +From: Aaron Kennedy +Date: Wed, 5 Oct 2011 13:01:30 +1000 +Subject: [PATCH 04/11] Introduce a QML compilation mode + +In QML mode, there is a second global object - known as the QML +global object. During property resolution, if a property is not +present on the JS global object, it is resolve on the QML global +object. + +This global object behavior is only enabled if a script is being +compiled in QML mode. The object to use as the QML global object +is passed as a parameter to the Script::Run() method. Any function +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 | 19 ++++++++-- + src/api.cc | 52 ++++++++++++++++++++++++----- + src/arm/code-stubs-arm.cc | 4 ++ + src/arm/full-codegen-arm.cc | 28 +++++++++------- + src/arm/lithium-arm.cc | 2 +- + src/arm/lithium-arm.h | 6 +++- + src/arm/lithium-codegen-arm.cc | 7 ++-- + src/arm/macro-assembler-arm.h | 5 +++ + src/ast-inl.h | 5 +++ + src/ast.h | 1 + + src/code-stubs.h | 2 +- + src/compiler.cc | 15 +++++++- + src/compiler.h | 16 +++++++-- + src/contexts.cc | 35 +++++++++++++++++++ + src/contexts.h | 4 ++ + src/execution.cc | 31 ++++++++++++++--- + src/execution.h | 8 ++++ + src/full-codegen.cc | 3 +- + src/full-codegen.h | 1 + + src/heap.cc | 4 ++ + src/hydrogen-instructions.h | 8 ++++- + src/hydrogen.cc | 2 + + src/ia32/code-stubs-ia32.cc | 5 +++ + src/ia32/full-codegen-ia32.cc | 28 +++++++++------- + src/ia32/lithium-codegen-ia32.cc | 7 ++-- + src/ia32/lithium-ia32.cc | 2 +- + src/ia32/lithium-ia32.h | 6 +++- + src/ia32/macro-assembler-ia32.h | 3 ++ + src/objects-inl.h | 2 + + src/objects.h | 4 ++ + src/parser.cc | 27 +++++++++++++-- + src/parser.h | 4 ++- + src/prettyprinter.cc | 3 ++ + src/runtime.cc | 68 +++++++++++++++++++++++++------------- + src/runtime.h | 8 ++-- + src/scopes.cc | 61 ++++++++++++++++++++++++++++++++++ + src/scopes.h | 8 ++++ + src/variables.cc | 3 +- + src/variables.h | 5 +++ + src/x64/code-stubs-x64.cc | 4 ++ + src/x64/full-codegen-x64.cc | 28 +++++++++------- + src/x64/lithium-codegen-x64.cc | 7 ++-- + src/x64/lithium-x64.cc | 2 +- + src/x64/lithium-x64.h | 6 +++ + src/x64/macro-assembler-x64.h | 5 +++ + 45 files changed, 445 insertions(+), 109 deletions(-) + +diff --git a/include/v8.h b/include/v8.h +index 3ef4dd6..193e2fe 100644 +--- a/include/v8.h ++++ b/include/v8.h +@@ -587,6 +587,11 @@ class ScriptOrigin { + */ + class V8EXPORT Script { + public: ++ enum CompileFlags { ++ Default = 0x00, ++ QmlMode = 0x01 ++ }; ++ + /** + * Compiles the specified script (context-independent). + * +@@ -605,7 +610,8 @@ class V8EXPORT Script { + static Local