From 78f4837926105eb238068e12401493f4a7a17dbc Mon Sep 17 00:00:00 2001 From: Ben Noordhuis Date: Wed, 25 Feb 2015 11:41:56 +0100 Subject: [PATCH] deps: upgrade v8 to 4.1.0.21 PR-URL: https://github.com/iojs/io.js/pull/952 Reviewed-By: Fedor Indutny Reviewed-By: Rod Vagg --- deps/v8/include/v8.h | 17 ++- deps/v8/src/api.cc | 35 +++-- deps/v8/src/flags.cc | 1 + deps/v8/src/generator.js | 4 +- deps/v8/src/globals.h | 2 +- deps/v8/src/heap/mark-compact.cc | 5 + deps/v8/src/heap/spaces.cc | 7 +- deps/v8/src/ic/ic.cc | 2 +- deps/v8/src/objects-inl.h | 1 + deps/v8/src/objects.cc | 121 +++++++++++++++--- deps/v8/src/objects.h | 17 ++- deps/v8/src/runtime/runtime-debug.cc | 3 +- deps/v8/src/runtime/runtime-regexp.cc | 2 +- deps/v8/src/serialize.cc | 65 ++++++++-- deps/v8/src/serialize.h | 44 ++++--- deps/v8/src/version.cc | 2 +- deps/v8/src/version.h | 5 +- deps/v8/test/cctest/test-api.cc | 2 +- deps/v8/test/cctest/test-serialize.cc | 50 ++++++++ .../test/mjsunit/es6/regress/regress-3902.js | 15 +++ .../v8/test/mjsunit/regress/regress-430201.js | 41 ++++++ deps/v8/tools/gen-postmortem-metadata.py | 14 +- 22 files changed, 368 insertions(+), 87 deletions(-) create mode 100644 deps/v8/test/mjsunit/es6/regress/regress-3902.js create mode 100644 deps/v8/test/mjsunit/regress/regress-430201.js diff --git a/deps/v8/include/v8.h b/deps/v8/include/v8.h index d35f2fcb27fabe..27aa5c12d12625 100644 --- a/deps/v8/include/v8.h +++ b/deps/v8/include/v8.h @@ -3899,6 +3899,9 @@ class V8_EXPORT FunctionTemplate : public Template { }; +enum class PropertyHandlerFlags { kNone = 0, kAllCanRead = 1 }; + + struct NamedPropertyHandlerConfiguration { NamedPropertyHandlerConfiguration( /** Note: getter is required **/ @@ -3907,13 +3910,15 @@ struct NamedPropertyHandlerConfiguration { GenericNamedPropertyQueryCallback query = 0, GenericNamedPropertyDeleterCallback deleter = 0, GenericNamedPropertyEnumeratorCallback enumerator = 0, - Handle data = Handle()) + Handle data = Handle(), + PropertyHandlerFlags flags = PropertyHandlerFlags::kNone) : getter(getter), setter(setter), query(query), deleter(deleter), enumerator(enumerator), - data(data) {} + data(data), + flags(flags) {} GenericNamedPropertyGetterCallback getter; GenericNamedPropertySetterCallback setter; @@ -3921,6 +3926,7 @@ struct NamedPropertyHandlerConfiguration { GenericNamedPropertyDeleterCallback deleter; GenericNamedPropertyEnumeratorCallback enumerator; Handle data; + PropertyHandlerFlags flags; }; @@ -3932,13 +3938,15 @@ struct IndexedPropertyHandlerConfiguration { IndexedPropertyQueryCallback query = 0, IndexedPropertyDeleterCallback deleter = 0, IndexedPropertyEnumeratorCallback enumerator = 0, - Handle data = Handle()) + Handle data = Handle(), + PropertyHandlerFlags flags = PropertyHandlerFlags::kNone) : getter(getter), setter(setter), query(query), deleter(deleter), enumerator(enumerator), - data(data) {} + data(data), + flags(flags) {} IndexedPropertyGetterCallback getter; IndexedPropertySetterCallback setter; @@ -3946,6 +3954,7 @@ struct IndexedPropertyHandlerConfiguration { IndexedPropertyDeleterCallback deleter; IndexedPropertyEnumeratorCallback enumerator; Handle data; + PropertyHandlerFlags flags; }; diff --git a/deps/v8/src/api.cc b/deps/v8/src/api.cc index 88d3c889b96cab..80afca28f343bd 100644 --- a/deps/v8/src/api.cc +++ b/deps/v8/src/api.cc @@ -1306,12 +1306,10 @@ void ObjectTemplate::SetAccessor(v8::Handle name, template -static void ObjectTemplateSetNamedPropertyHandler(ObjectTemplate* templ, - Getter getter, Setter setter, - Query query, Deleter remover, - Enumerator enumerator, - Handle data, - bool can_intercept_symbols) { +static void ObjectTemplateSetNamedPropertyHandler( + ObjectTemplate* templ, Getter getter, Setter setter, Query query, + Deleter remover, Enumerator enumerator, Handle data, + bool can_intercept_symbols, PropertyHandlerFlags flags) { i::Isolate* isolate = Utils::OpenHandle(templ)->GetIsolate(); ENTER_V8(isolate); i::HandleScope scope(isolate); @@ -1319,10 +1317,8 @@ static void ObjectTemplateSetNamedPropertyHandler(ObjectTemplate* templ, i::FunctionTemplateInfo* constructor = i::FunctionTemplateInfo::cast(Utils::OpenHandle(templ)->constructor()); i::Handle cons(constructor); - i::Handle struct_obj = - isolate->factory()->NewStruct(i::INTERCEPTOR_INFO_TYPE); - i::Handle obj = - i::Handle::cast(struct_obj); + auto obj = i::Handle::cast( + isolate->factory()->NewStruct(i::INTERCEPTOR_INFO_TYPE)); if (getter != 0) SET_FIELD_WRAPPED(obj, set_getter, getter); if (setter != 0) SET_FIELD_WRAPPED(obj, set_setter, setter); @@ -1331,6 +1327,8 @@ static void ObjectTemplateSetNamedPropertyHandler(ObjectTemplate* templ, if (enumerator != 0) SET_FIELD_WRAPPED(obj, set_enumerator, enumerator); obj->set_flags(0); obj->set_can_intercept_symbols(can_intercept_symbols); + obj->set_all_can_read(static_cast(flags) & + static_cast(PropertyHandlerFlags::kAllCanRead)); if (data.IsEmpty()) { data = v8::Undefined(reinterpret_cast(isolate)); @@ -1345,15 +1343,16 @@ void ObjectTemplate::SetNamedPropertyHandler( NamedPropertyQueryCallback query, NamedPropertyDeleterCallback remover, NamedPropertyEnumeratorCallback enumerator, Handle data) { ObjectTemplateSetNamedPropertyHandler(this, getter, setter, query, remover, - enumerator, data, false); + enumerator, data, false, + PropertyHandlerFlags::kNone); } void ObjectTemplate::SetHandler( const NamedPropertyHandlerConfiguration& config) { - ObjectTemplateSetNamedPropertyHandler(this, config.getter, config.setter, - config.query, config.deleter, - config.enumerator, config.data, true); + ObjectTemplateSetNamedPropertyHandler( + this, config.getter, config.setter, config.query, config.deleter, + config.enumerator, config.data, true, config.flags); } @@ -1409,10 +1408,8 @@ void ObjectTemplate::SetHandler( i::FunctionTemplateInfo* constructor = i::FunctionTemplateInfo::cast( Utils::OpenHandle(this)->constructor()); i::Handle cons(constructor); - i::Handle struct_obj = - isolate->factory()->NewStruct(i::INTERCEPTOR_INFO_TYPE); - i::Handle obj = - i::Handle::cast(struct_obj); + auto obj = i::Handle::cast( + isolate->factory()->NewStruct(i::INTERCEPTOR_INFO_TYPE)); if (config.getter != 0) SET_FIELD_WRAPPED(obj, set_getter, config.getter); if (config.setter != 0) SET_FIELD_WRAPPED(obj, set_setter, config.setter); @@ -1422,6 +1419,8 @@ void ObjectTemplate::SetHandler( SET_FIELD_WRAPPED(obj, set_enumerator, config.enumerator); } obj->set_flags(0); + obj->set_all_can_read(static_cast(config.flags) & + static_cast(PropertyHandlerFlags::kAllCanRead)); v8::Local data = config.data; if (data.IsEmpty()) { diff --git a/deps/v8/src/flags.cc b/deps/v8/src/flags.cc index 2aa4e6bd48587e..5e33bdaeec8862 100644 --- a/deps/v8/src/flags.cc +++ b/deps/v8/src/flags.cc @@ -556,6 +556,7 @@ uint32_t FlagList::Hash() { for (size_t i = 0; i < num_flags; ++i) { Flag* current = &flags[i]; if (!current->IsDefault()) { + modified_args_as_string << i; modified_args_as_string << *current; } } diff --git a/deps/v8/src/generator.js b/deps/v8/src/generator.js index 8e9ed8f2566a7e..9ab7dcb9aab9b7 100644 --- a/deps/v8/src/generator.js +++ b/deps/v8/src/generator.js @@ -97,7 +97,7 @@ function SetUpGenerators() { %AddNamedProperty(GeneratorObjectPrototype, symbolIterator, GeneratorObjectIterator, DONT_ENUM | DONT_DELETE | READ_ONLY); %AddNamedProperty(GeneratorObjectPrototype, "constructor", - GeneratorFunctionPrototype, DONT_ENUM | DONT_DELETE | READ_ONLY); + GeneratorFunctionPrototype, DONT_ENUM | READ_ONLY); %AddNamedProperty(GeneratorObjectPrototype, symbolToStringTag, "Generator", DONT_ENUM | READ_ONLY); %InternalSetPrototype(GeneratorFunctionPrototype, $Function.prototype); @@ -105,7 +105,7 @@ function SetUpGenerators() { symbolToStringTag, "GeneratorFunction", DONT_ENUM | READ_ONLY); %SetCode(GeneratorFunctionPrototype, GeneratorFunctionPrototypeConstructor); %AddNamedProperty(GeneratorFunctionPrototype, "constructor", - GeneratorFunction, DONT_ENUM | DONT_DELETE | READ_ONLY); + GeneratorFunction, DONT_ENUM | READ_ONLY); %InternalSetPrototype(GeneratorFunction, $Function); %SetCode(GeneratorFunction, GeneratorFunctionConstructor); } diff --git a/deps/v8/src/globals.h b/deps/v8/src/globals.h index 48bb030b826f64..52ec2aaaa41817 100644 --- a/deps/v8/src/globals.h +++ b/deps/v8/src/globals.h @@ -84,7 +84,7 @@ namespace internal { // Determine whether double field unboxing feature is enabled. #if (V8_TARGET_ARCH_X64 || V8_TARGET_ARCH_ARM64) -#define V8_DOUBLE_FIELDS_UNBOXING 1 +#define V8_DOUBLE_FIELDS_UNBOXING 0 #else #define V8_DOUBLE_FIELDS_UNBOXING 0 #endif diff --git a/deps/v8/src/heap/mark-compact.cc b/deps/v8/src/heap/mark-compact.cc index fa127db6129c0f..c9a310a3f7aee0 100644 --- a/deps/v8/src/heap/mark-compact.cc +++ b/deps/v8/src/heap/mark-compact.cc @@ -3052,6 +3052,11 @@ void MarkCompactCollector::EvacuatePages() { // have an emergency page and the space still has room for that. if (space->HasEmergencyMemory() && space->CanExpand()) { EvacuateLiveObjectsFromPage(p); + // Unlink the page from the list of pages here. We must not iterate + // over that page later (e.g. when scan on scavenge pages are + // processed). The page itself will be freed later and is still + // reachable from the evacuation candidates list. + p->Unlink(); } else { // Without room for expansion evacuation is not guaranteed to succeed. // Pessimistically abandon unevacuated pages. diff --git a/deps/v8/src/heap/spaces.cc b/deps/v8/src/heap/spaces.cc index 3802e470bd454a..060052e706cf41 100644 --- a/deps/v8/src/heap/spaces.cc +++ b/deps/v8/src/heap/spaces.cc @@ -1142,7 +1142,12 @@ void PagedSpace::ReleasePage(Page* page) { allocation_info_.set_limit(NULL); } - page->Unlink(); + // If page is still in a list, unlink it from that list. + if (page->next_chunk() != NULL) { + DCHECK(page->prev_chunk() != NULL); + page->Unlink(); + } + if (page->IsFlagSet(MemoryChunk::CONTAINS_ONLY_DATA)) { heap()->isolate()->memory_allocator()->Free(page); } else { diff --git a/deps/v8/src/ic/ic.cc b/deps/v8/src/ic/ic.cc index 48cef68f5ac652..0707536b84d1c7 100644 --- a/deps/v8/src/ic/ic.cc +++ b/deps/v8/src/ic/ic.cc @@ -2924,7 +2924,7 @@ RUNTIME_FUNCTION(LoadElementWithInterceptor) { Handle result; ASSIGN_RETURN_FAILURE_ON_EXCEPTION( isolate, result, - JSObject::GetElementWithInterceptor(receiver, receiver, index)); + JSObject::GetElementWithInterceptor(receiver, receiver, index, true)); return *result; } diff --git a/deps/v8/src/objects-inl.h b/deps/v8/src/objects-inl.h index 485560f2933ebe..fdfadb1883905b 100644 --- a/deps/v8/src/objects-inl.h +++ b/deps/v8/src/objects-inl.h @@ -5517,6 +5517,7 @@ ACCESSORS(InterceptorInfo, data, Object, kDataOffset) SMI_ACCESSORS(InterceptorInfo, flags, kFlagsOffset) BOOL_ACCESSORS(InterceptorInfo, flags, can_intercept_symbols, kCanInterceptSymbolsBit) +BOOL_ACCESSORS(InterceptorInfo, flags, all_can_read, kAllCanReadBit) ACCESSORS(CallHandlerInfo, callback, Object, kCallbackOffset) ACCESSORS(CallHandlerInfo, data, Object, kDataOffset) diff --git a/deps/v8/src/objects.cc b/deps/v8/src/objects.cc index 414306f2b46555..6b64c3fb21782d 100644 --- a/deps/v8/src/objects.cc +++ b/deps/v8/src/objects.cc @@ -572,12 +572,19 @@ MaybeHandle Object::SetPropertyWithDefinedSetter( static bool FindAllCanReadHolder(LookupIterator* it) { - for (; it->IsFound(); it->Next()) { + // Skip current iteration, it's in state ACCESS_CHECK or INTERCEPTOR, both of + // which have already been checked. + DCHECK(it->state() == LookupIterator::ACCESS_CHECK || + it->state() == LookupIterator::INTERCEPTOR); + for (it->Next(); it->IsFound(); it->Next()) { if (it->state() == LookupIterator::ACCESSOR) { - Handle accessors = it->GetAccessors(); + auto accessors = it->GetAccessors(); if (accessors->IsAccessorInfo()) { if (AccessorInfo::cast(*accessors)->all_can_read()) return true; } + } else if (it->state() == LookupIterator::INTERCEPTOR) { + auto holder = it->GetHolder(); + if (holder->GetNamedInterceptor()->all_can_read()) return true; } } return false; @@ -587,10 +594,18 @@ static bool FindAllCanReadHolder(LookupIterator* it) { MaybeHandle JSObject::GetPropertyWithFailedAccessCheck( LookupIterator* it) { Handle checked = it->GetHolder(); - if (FindAllCanReadHolder(it)) { - return GetPropertyWithAccessor(it->GetReceiver(), it->name(), - it->GetHolder(), - it->GetAccessors()); + while (FindAllCanReadHolder(it)) { + if (it->state() == LookupIterator::ACCESSOR) { + return GetPropertyWithAccessor(it->GetReceiver(), it->name(), + it->GetHolder(), + it->GetAccessors()); + } + DCHECK_EQ(LookupIterator::INTERCEPTOR, it->state()); + auto receiver = Handle::cast(it->GetReceiver()); + auto result = GetPropertyWithInterceptor(it->GetHolder(), + receiver, it->name()); + if (it->isolate()->has_scheduled_exception()) break; + if (!result.is_null()) return result; } it->isolate()->ReportFailedAccessCheck(checked, v8::ACCESS_GET); RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(it->isolate(), Object); @@ -601,8 +616,16 @@ MaybeHandle JSObject::GetPropertyWithFailedAccessCheck( Maybe JSObject::GetPropertyAttributesWithFailedAccessCheck( LookupIterator* it) { Handle checked = it->GetHolder(); - if (FindAllCanReadHolder(it)) - return maybe(it->property_details().attributes()); + while (FindAllCanReadHolder(it)) { + if (it->state() == LookupIterator::ACCESSOR) { + return maybe(it->property_details().attributes()); + } + DCHECK_EQ(LookupIterator::INTERCEPTOR, it->state()); + auto result = GetPropertyAttributesWithInterceptor( + it->GetHolder(), it->GetReceiver(), it->name()); + if (it->isolate()->has_scheduled_exception()) break; + if (result.has_value && result.value != ABSENT) return result; + } it->isolate()->ReportFailedAccessCheck(checked, v8::ACCESS_HAS); RETURN_VALUE_IF_SCHEDULED_EXCEPTION(it->isolate(), Maybe()); @@ -736,6 +759,65 @@ Handle JSObject::DeleteNormalizedProperty(Handle object, } +static MaybeHandle FindIndexedAllCanReadHolder( + Isolate* isolate, Handle js_object, + PrototypeIterator::WhereToStart where_to_start) { + for (PrototypeIterator iter(isolate, js_object, where_to_start); + !iter.IsAtEnd(); iter.Advance()) { + auto curr = PrototypeIterator::GetCurrent(iter); + if (!curr->IsJSObject()) break; + auto obj = Handle::cast(curr); + if (!obj->HasIndexedInterceptor()) continue; + if (obj->GetIndexedInterceptor()->all_can_read()) return obj; + } + return MaybeHandle(); +} + + +MaybeHandle JSObject::GetElementWithFailedAccessCheck( + Isolate* isolate, Handle object, Handle receiver, + uint32_t index) { + Handle holder = object; + PrototypeIterator::WhereToStart where_to_start = + PrototypeIterator::START_AT_RECEIVER; + while (true) { + auto all_can_read_holder = + FindIndexedAllCanReadHolder(isolate, holder, where_to_start); + if (!all_can_read_holder.ToHandle(&holder)) break; + auto result = + JSObject::GetElementWithInterceptor(holder, receiver, index, false); + if (isolate->has_scheduled_exception()) break; + if (!result.is_null()) return result; + where_to_start = PrototypeIterator::START_AT_PROTOTYPE; + } + isolate->ReportFailedAccessCheck(object, v8::ACCESS_GET); + RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object); + return isolate->factory()->undefined_value(); +} + + +Maybe JSObject::GetElementAttributesWithFailedAccessCheck( + Isolate* isolate, Handle object, Handle receiver, + uint32_t index) { + Handle holder = object; + PrototypeIterator::WhereToStart where_to_start = + PrototypeIterator::START_AT_RECEIVER; + while (true) { + auto all_can_read_holder = + FindIndexedAllCanReadHolder(isolate, holder, where_to_start); + if (!all_can_read_holder.ToHandle(&holder)) break; + auto result = + JSObject::GetElementAttributeFromInterceptor(object, receiver, index); + if (isolate->has_scheduled_exception()) break; + if (result.has_value && result.value != ABSENT) return result; + where_to_start = PrototypeIterator::START_AT_PROTOTYPE; + } + isolate->ReportFailedAccessCheck(object, v8::ACCESS_HAS); + RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Maybe()); + return maybe(ABSENT); +} + + MaybeHandle Object::GetElementWithReceiver(Isolate* isolate, Handle object, Handle receiver, @@ -768,14 +850,14 @@ MaybeHandle Object::GetElementWithReceiver(Isolate* isolate, // Check access rights if needed. if (js_object->IsAccessCheckNeeded()) { if (!isolate->MayIndexedAccess(js_object, index, v8::ACCESS_GET)) { - isolate->ReportFailedAccessCheck(js_object, v8::ACCESS_GET); - RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object); - return isolate->factory()->undefined_value(); + return JSObject::GetElementWithFailedAccessCheck(isolate, js_object, + receiver, index); } } if (js_object->HasIndexedInterceptor()) { - return JSObject::GetElementWithInterceptor(js_object, receiver, index); + return JSObject::GetElementWithInterceptor(js_object, receiver, index, + true); } if (js_object->elements() != isolate->heap()->empty_fixed_array()) { @@ -4184,9 +4266,8 @@ Maybe JSObject::GetElementAttributeWithReceiver( // Check access rights if needed. if (object->IsAccessCheckNeeded()) { if (!isolate->MayIndexedAccess(object, index, v8::ACCESS_HAS)) { - isolate->ReportFailedAccessCheck(object, v8::ACCESS_HAS); - RETURN_VALUE_IF_SCHEDULED_EXCEPTION(isolate, Maybe()); - return maybe(ABSENT); + return GetElementAttributesWithFailedAccessCheck(isolate, object, + receiver, index); } } @@ -13383,10 +13464,10 @@ MaybeHandle JSArray::ReadOnlyLengthError(Handle array) { } -MaybeHandle JSObject::GetElementWithInterceptor( - Handle object, - Handle receiver, - uint32_t index) { +MaybeHandle JSObject::GetElementWithInterceptor(Handle object, + Handle receiver, + uint32_t index, + bool check_prototype) { Isolate* isolate = object->GetIsolate(); // Make sure that the top context does not change when doing @@ -13411,6 +13492,8 @@ MaybeHandle JSObject::GetElementWithInterceptor( } } + if (!check_prototype) return MaybeHandle(); + ElementsAccessor* handler = object->GetElementsAccessor(); Handle result; ASSIGN_RETURN_ON_EXCEPTION( diff --git a/deps/v8/src/objects.h b/deps/v8/src/objects.h index f2f2e495b44ec2..c32f9f6cca9e70 100644 --- a/deps/v8/src/objects.h +++ b/deps/v8/src/objects.h @@ -1971,9 +1971,8 @@ class JSObject: public JSReceiver { // Returns the index'th element. // The undefined object if index is out of bounds. MUST_USE_RESULT static MaybeHandle GetElementWithInterceptor( - Handle object, - Handle receiver, - uint32_t index); + Handle object, Handle receiver, uint32_t index, + bool check_prototype); enum SetFastElementsCapacitySmiMode { kAllowSmiElements, @@ -2336,6 +2335,14 @@ class JSObject: public JSReceiver { Handle value, StrictMode strict_mode, bool check_prototype = true); + MUST_USE_RESULT static MaybeHandle GetElementWithFailedAccessCheck( + Isolate* isolate, Handle object, Handle receiver, + uint32_t index); + MUST_USE_RESULT static Maybe + GetElementAttributesWithFailedAccessCheck(Isolate* isolate, + Handle object, + Handle receiver, + uint32_t index); MUST_USE_RESULT static MaybeHandle SetPropertyWithFailedAccessCheck( LookupIterator* it, Handle value, StrictMode strict_mode); @@ -7062,8 +7069,6 @@ class SharedFunctionInfo: public HeapObject { static const int kUniqueIdOffset = kFeedbackVectorOffset + kPointerSize; static const int kLastPointerFieldOffset = kUniqueIdOffset; #else - // Just to not break the postmortem support with conditional offsets - static const int kUniqueIdOffset = kFeedbackVectorOffset; static const int kLastPointerFieldOffset = kFeedbackVectorOffset; #endif @@ -10642,6 +10647,7 @@ class InterceptorInfo: public Struct { DECL_ACCESSORS(enumerator, Object) DECL_ACCESSORS(data, Object) DECL_BOOLEAN_ACCESSORS(can_intercept_symbols) + DECL_BOOLEAN_ACCESSORS(all_can_read) inline int flags() const; inline void set_flags(int flags); @@ -10662,6 +10668,7 @@ class InterceptorInfo: public Struct { static const int kSize = kFlagsOffset + kPointerSize; static const int kCanInterceptSymbolsBit = 0; + static const int kAllCanReadBit = 1; private: DISALLOW_IMPLICIT_CONSTRUCTORS(InterceptorInfo); diff --git a/deps/v8/src/runtime/runtime-debug.cc b/deps/v8/src/runtime/runtime-debug.cc index 12c5a0d84f3567..9b71a4f95e0117 100644 --- a/deps/v8/src/runtime/runtime-debug.cc +++ b/deps/v8/src/runtime/runtime-debug.cc @@ -246,7 +246,8 @@ RUNTIME_FUNCTION(Runtime_DebugIndexedInterceptorElementValue) { CONVERT_NUMBER_CHECKED(uint32_t, index, Uint32, args[1]); Handle result; ASSIGN_RETURN_FAILURE_ON_EXCEPTION( - isolate, result, JSObject::GetElementWithInterceptor(obj, obj, index)); + isolate, result, + JSObject::GetElementWithInterceptor(obj, obj, index, true)); return *result; } diff --git a/deps/v8/src/runtime/runtime-regexp.cc b/deps/v8/src/runtime/runtime-regexp.cc index be9adfff41e5ac..9296a4b8a9e15d 100644 --- a/deps/v8/src/runtime/runtime-regexp.cc +++ b/deps/v8/src/runtime/runtime-regexp.cc @@ -278,7 +278,7 @@ void CompiledReplacement::Apply(ReplacementStringBuilder* builder, } -void FindOneByteStringIndices(Vector subject, char pattern, +void FindOneByteStringIndices(Vector subject, uint8_t pattern, ZoneList* indices, unsigned int limit, Zone* zone) { DCHECK(limit > 0); diff --git a/deps/v8/src/serialize.cc b/deps/v8/src/serialize.cc index 01c55a1226efed..c5f8b6344efce4 100644 --- a/deps/v8/src/serialize.cc +++ b/deps/v8/src/serialize.cc @@ -2054,6 +2054,10 @@ void Serializer::Pad() { for (unsigned i = 0; i < sizeof(int32_t) - 1; i++) { sink_->Put(kNop, "Padding"); } + // Pad up to pointer size for checksum. + while (!IsAligned(sink_->Position(), kPointerAlignment)) { + sink_->Put(kNop, "Padding"); + } } @@ -2394,6 +2398,41 @@ Vector SnapshotData::Payload() const { } +class Checksum { + public: + explicit Checksum(Vector payload) { + // Fletcher's checksum. Modified to reduce 64-bit sums to 32-bit. + uintptr_t a = 1; + uintptr_t b = 0; + const uintptr_t* cur = reinterpret_cast(payload.start()); + DCHECK(IsAligned(payload.length(), kIntptrSize)); + const uintptr_t* end = cur + payload.length() / kIntptrSize; + while (cur < end) { + // Unsigned overflow expected and intended. + a += *cur++; + b += a; + } +#if V8_HOST_ARCH_64_BIT + a ^= a >> 32; + b ^= b >> 32; +#endif // V8_HOST_ARCH_64_BIT + a_ = static_cast(a); + b_ = static_cast(b); + } + + bool Check(uint32_t a, uint32_t b) const { return a == a_ && b == b_; } + + uint32_t a() const { return a_; } + uint32_t b() const { return b_; } + + private: + uint32_t a_; + uint32_t b_; + + DISALLOW_COPY_AND_ASSIGN(Checksum); +}; + + SerializedCodeData::SerializedCodeData(const List& payload, const CodeSerializer& cs) { DisallowHeapAllocation no_gc; @@ -2412,12 +2451,20 @@ SerializedCodeData::SerializedCodeData(const List& payload, AllocateData(size); // Set header values. - SetHeaderValue(kCheckSumOffset, CheckSum(cs.source())); + SetHeaderValue(kVersionHashOffset, Version::Hash()); + SetHeaderValue(kSourceHashOffset, SourceHash(cs.source())); + SetHeaderValue(kCpuFeaturesOffset, + static_cast(CpuFeatures::SupportedFeatures())); + SetHeaderValue(kFlagHashOffset, FlagList::Hash()); SetHeaderValue(kNumInternalizedStringsOffset, cs.num_internalized_strings()); SetHeaderValue(kReservationsOffset, reservations.length()); SetHeaderValue(kNumCodeStubKeysOffset, num_stub_keys); SetHeaderValue(kPayloadLengthOffset, payload.length()); + Checksum checksum(payload.ToConstVector()); + SetHeaderValue(kChecksum1Offset, checksum.a()); + SetHeaderValue(kChecksum2Offset, checksum.b()); + // Copy reservation chunk sizes. CopyBytes(data_ + kHeaderSize, reinterpret_cast(reservations.begin()), reservation_size); @@ -2432,14 +2479,14 @@ SerializedCodeData::SerializedCodeData(const List& payload, } -bool SerializedCodeData::IsSane(String* source) { - return GetHeaderValue(kCheckSumOffset) == CheckSum(source) && - Payload().length() >= SharedFunctionInfo::kSize; -} - - -int SerializedCodeData::CheckSum(String* string) { - return Version::Hash() ^ string->length(); +bool SerializedCodeData::IsSane(String* source) const { + return GetHeaderValue(kVersionHashOffset) == Version::Hash() && + GetHeaderValue(kSourceHashOffset) == SourceHash(source) && + GetHeaderValue(kCpuFeaturesOffset) == + static_cast(CpuFeatures::SupportedFeatures()) && + GetHeaderValue(kFlagHashOffset) == FlagList::Hash() && + Checksum(Payload()).Check(GetHeaderValue(kChecksum1Offset), + GetHeaderValue(kChecksum2Offset)); } diff --git a/deps/v8/src/serialize.h b/deps/v8/src/serialize.h index bd0c423a6aa828..da750cb3c6dc12 100644 --- a/deps/v8/src/serialize.h +++ b/deps/v8/src/serialize.h @@ -481,12 +481,14 @@ class SerializedData { class IsLastChunkBits : public BitField {}; protected: - void SetHeaderValue(int offset, int value) { - reinterpret_cast(data_)[offset] = value; + void SetHeaderValue(int offset, uint32_t value) { + memcpy(reinterpret_cast(data_) + offset, &value, sizeof(value)); } - int GetHeaderValue(int offset) const { - return reinterpret_cast(data_)[offset]; + uint32_t GetHeaderValue(int offset) const { + uint32_t value; + memcpy(&value, reinterpret_cast(data_) + offset, sizeof(value)); + return value; } void AllocateData(int size); @@ -920,22 +922,32 @@ class SerializedCodeData : public SerializedData { explicit SerializedCodeData(ScriptData* data) : SerializedData(const_cast(data->data()), data->length()) {} - bool IsSane(String* source); + bool IsSane(String* source) const; - int CheckSum(String* source); + static uint32_t SourceHash(String* source) { return source->length(); } // The data header consists of int-sized entries: // [0] version hash - // [1] number of internalized strings - // [2] number of code stub keys - // [3] number of reservation size entries - // [4] payload length - static const int kCheckSumOffset = 0; - static const int kNumInternalizedStringsOffset = 1; - static const int kReservationsOffset = 2; - static const int kNumCodeStubKeysOffset = 3; - static const int kPayloadLengthOffset = 4; - static const int kHeaderSize = (kPayloadLengthOffset + 1) * kIntSize; + // [1] source hash + // [2] cpu features + // [3] flag hash + // [4] number of internalized strings + // [5] number of code stub keys + // [6] number of reservation size entries + // [7] payload length + // [8] checksum 1 + // [9] checksum 2 + static const int kVersionHashOffset = 0; + static const int kSourceHashOffset = 1; + static const int kCpuFeaturesOffset = 2; + static const int kFlagHashOffset = 3; + static const int kNumInternalizedStringsOffset = 4; + static const int kReservationsOffset = 5; + static const int kNumCodeStubKeysOffset = 6; + static const int kPayloadLengthOffset = 7; + static const int kChecksum1Offset = 8; + static const int kChecksum2Offset = 9; + static const int kHeaderSize = (kChecksum2Offset + 1) * kIntSize; }; } } // namespace v8::internal diff --git a/deps/v8/src/version.cc b/deps/v8/src/version.cc index 3b1c220f57db26..edcf2be2db4a86 100644 --- a/deps/v8/src/version.cc +++ b/deps/v8/src/version.cc @@ -35,7 +35,7 @@ #define MAJOR_VERSION 4 #define MINOR_VERSION 1 #define BUILD_NUMBER 0 -#define PATCH_LEVEL 14 +#define PATCH_LEVEL 21 // Use 1 for candidates and 0 otherwise. // (Boolean macro values are not supported by all preprocessors.) #define IS_CANDIDATE_VERSION 0 diff --git a/deps/v8/src/version.h b/deps/v8/src/version.h index 008ed276548f16..dbcec1b27d427b 100644 --- a/deps/v8/src/version.h +++ b/deps/v8/src/version.h @@ -18,8 +18,9 @@ class Version { static int GetBuild() { return build_; } static int GetPatch() { return patch_; } static bool IsCandidate() { return candidate_; } - static int Hash() { - return static_cast(base::hash_combine(major_, minor_, build_, patch_)); + static uint32_t Hash() { + return static_cast( + base::hash_combine(major_, minor_, build_, patch_)); } // Calculate the V8 version string. diff --git a/deps/v8/test/cctest/test-api.cc b/deps/v8/test/cctest/test-api.cc index d18059cd54bdad..06cf5532e244e3 100644 --- a/deps/v8/test/cctest/test-api.cc +++ b/deps/v8/test/cctest/test-api.cc @@ -24540,7 +24540,7 @@ TEST(StreamingUtf8ScriptWithMultipleMultibyteCharactersSomeSplit2) { void TestInvalidCacheData(v8::ScriptCompiler::CompileOptions option) { - const char* garbage = "garbage garbage garbage garbage."; + const char* garbage = "garbage garbage garbage garbage garbage garbage"; const uint8_t* data = reinterpret_cast(garbage); int length = 16; v8::ScriptCompiler::CachedData* cached_data = diff --git a/deps/v8/test/cctest/test-serialize.cc b/deps/v8/test/cctest/test-serialize.cc index acd904f4b79dfd..45da25024f74c1 100644 --- a/deps/v8/test/cctest/test-serialize.cc +++ b/deps/v8/test/cctest/test-serialize.cc @@ -1156,6 +1156,56 @@ TEST(SerializeToplevelIsolates) { } +TEST(SerializeToplevelFlagChange) { + FLAG_serialize_toplevel = true; + + const char* source = "function f() { return 'abc'; }; f() + 'def'"; + v8::ScriptCompiler::CachedData* cache; + + v8::Isolate* isolate1 = v8::Isolate::New(); + { + v8::Isolate::Scope iscope(isolate1); + v8::HandleScope scope(isolate1); + v8::Local context = v8::Context::New(isolate1); + v8::Context::Scope context_scope(context); + + v8::Local source_str = v8_str(source); + v8::ScriptOrigin origin(v8_str("test")); + v8::ScriptCompiler::Source source(source_str, origin); + v8::Local script = v8::ScriptCompiler::CompileUnbound( + isolate1, &source, v8::ScriptCompiler::kProduceCodeCache); + const v8::ScriptCompiler::CachedData* data = source.GetCachedData(); + CHECK(data); + // Persist cached data. + uint8_t* buffer = NewArray(data->length); + MemCopy(buffer, data->data, data->length); + cache = new v8::ScriptCompiler::CachedData( + buffer, data->length, v8::ScriptCompiler::CachedData::BufferOwned); + + v8::Local result = script->BindToCurrentContext()->Run(); + CHECK(result->ToString(isolate1)->Equals(v8_str("abcdef"))); + } + isolate1->Dispose(); + + v8::Isolate* isolate2 = v8::Isolate::New(); + FLAG_allow_natives_syntax = true; // Flag change should trigger cache reject. + { + v8::Isolate::Scope iscope(isolate2); + v8::HandleScope scope(isolate2); + v8::Local context = v8::Context::New(isolate2); + v8::Context::Scope context_scope(context); + + v8::Local source_str = v8_str(source); + v8::ScriptOrigin origin(v8_str("test")); + v8::ScriptCompiler::Source source(source_str, origin, cache); + v8::ScriptCompiler::CompileUnbound(isolate2, &source, + v8::ScriptCompiler::kConsumeCodeCache); + CHECK(cache->rejected); + } + isolate2->Dispose(); +} + + TEST(SerializeWithHarmonyScoping) { FLAG_serialize_toplevel = true; FLAG_harmony_scoping = true; diff --git a/deps/v8/test/mjsunit/es6/regress/regress-3902.js b/deps/v8/test/mjsunit/es6/regress/regress-3902.js new file mode 100644 index 00000000000000..768a4a1d075e38 --- /dev/null +++ b/deps/v8/test/mjsunit/es6/regress/regress-3902.js @@ -0,0 +1,15 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +function* g() {} +assertTrue(Object.getOwnPropertyDescriptor(g.__proto__, "constructor").configurable); +assertTrue(Object.getOwnPropertyDescriptor(g.prototype.__proto__, "constructor").configurable); + +function FakeGeneratorFunctionConstructor() {} +Object.defineProperty(g.__proto__, "constructor", {value: FakeGeneratorFunctionConstructor}); +assertSame(g.__proto__.constructor, FakeGeneratorFunctionConstructor); + +function FakeGeneratorObjectConstructor() {} +Object.defineProperty(g.prototype.__proto__, "constructor", {value: FakeGeneratorObjectConstructor}); +assertSame(g.prototype.__proto__.constructor, FakeGeneratorObjectConstructor); diff --git a/deps/v8/test/mjsunit/regress/regress-430201.js b/deps/v8/test/mjsunit/regress/regress-430201.js new file mode 100644 index 00000000000000..b53383e22e4553 --- /dev/null +++ b/deps/v8/test/mjsunit/regress/regress-430201.js @@ -0,0 +1,41 @@ +// Copyright 2010 the V8 project authors. All rights reserved. +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Flags: --allow-natives-syntax --expose-gc + +var array_1 = []; + +%SetFlags("--stress-compaction"); +for (var a = 0; a < 10000; a++) { array_1[a * 100] = 0; } + +gc(); +gc(); + +var array_2 = []; +for (var i = 0; i < 321361; i++) { + array_2[i] = String.fromCharCode(i)[0]; +} diff --git a/deps/v8/tools/gen-postmortem-metadata.py b/deps/v8/tools/gen-postmortem-metadata.py index 62e103a7359714..04a1ea87f4afaf 100644 --- a/deps/v8/tools/gen-postmortem-metadata.py +++ b/deps/v8/tools/gen-postmortem-metadata.py @@ -70,6 +70,8 @@ { 'name': 'ExternalStringTag', 'value': 'kExternalStringTag' }, { 'name': 'SlicedStringTag', 'value': 'kSlicedStringTag' }, + { 'name': 'FailureTag', 'value': 'kFailureTag' }, + { 'name': 'FailureTagMask', 'value': 'kFailureTagMask' }, { 'name': 'HeapObjectTag', 'value': 'kHeapObjectTag' }, { 'name': 'HeapObjectTagMask', 'value': 'kHeapObjectTagMask' }, { 'name': 'SmiTag', 'value': 'kSmiTag' }, @@ -92,6 +94,8 @@ 'value': 'DescriptorArray::kFirstIndex' }, { 'name': 'prop_type_field', 'value': 'FIELD' }, + { 'name': 'prop_type_first_phantom', + 'value': 'TRANSITION' }, { 'name': 'prop_type_mask', 'value': 'PropertyDetails::TypeField::kMask' }, { 'name': 'prop_index_mask', @@ -116,9 +120,9 @@ 'value': 'DICTIONARY_ELEMENTS' }, { 'name': 'bit_field2_elements_kind_mask', - 'value': 'Map::ElementsKindBits::kMask' }, + 'value': 'Map::kElementsKindMask' }, { 'name': 'bit_field2_elements_kind_shift', - 'value': 'Map::ElementsKindBits::kShift' }, + 'value': 'Map::kElementsKindShift' }, { 'name': 'bit_field3_dictionary_map_shift', 'value': 'Map::DictionaryMap::kShift' }, @@ -192,9 +196,9 @@ * This file is generated by %s. Do not edit directly. */ -#include "src/v8.h" -#include "src/frames.h" -#include "src/frames-inl.h" /* for architecture-specific frame constants */ +#include "v8.h" +#include "frames.h" +#include "frames-inl.h" /* for architecture-specific frame constants */ using namespace v8::internal;